/// <summary> /// loads the game state from blob storage, initializes it if it doesn't already exist /// </summary> private void LoadState() { MemoryStream tmpStream = new MemoryStream(); try { stateBlob.DownloadToStreamAsync(tmpStream).Wait(); devicelist = JsonConvert.DeserializeObject <List <bpDevice> >(Encoding.UTF8.GetString(tmpStream.ToArray())); } catch (Exception ex) { // if the container doesn't already exist, create it and an empty device collection if (ex.InnerException is StorageException && ex.InnerException.Message.Contains("does not exist")) { container.CreateIfNotExistsAsync().Wait(); // create container devicelist = new List <bpDevice>(); // create an empty device list } } // initialize collection with game state "device" if it doesn't already exist if (devicelist.Count <= 0) { bpDevice statedevice = new bpDevice() { deviceId = "GameState", accessToken = "false" }; devicelist.Add(statedevice); // add to the list } }
public async static Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = "devices")] HttpRequestMessage req, TraceWriter log) { log.Info("RegisterDevice processed a request."); HttpResponseMessage rtnResponse = null; try { // Get request body, should contain deviceId and accessToken //bpDevice deviceData = JsonConvert.DeserializeObject<bpDevice>(await req.Content.ReadAsStringAsync()); bpDevice deviceData = await req.Content.ReadAsAsync <bpDevice>(); GameStateManager gameState = new GameStateManager(); // get game state if (!gameState.IsRunning) // if game isn't running { gameState.RegisterDevice(deviceData); // register the device log.Info($"Registering Device {deviceData.deviceId}"); } // respond to request rtnResponse = req.CreateResponse(HttpStatusCode.OK); } catch (RuntimeBinderException ex) { // "deviceData didn't deserialize properly rtnResponse = req.CreateResponse(HttpStatusCode.BadRequest, @"Please pass the device ID and Access Token in the body of your request: { ""deviceID"" : ""value"", ""accesstoken"" : ""value""}"); } catch (Exception ex) { // "name property doesn't exist in request body rtnResponse = req.CreateResponse(HttpStatusCode.InternalServerError, $"An unhandled exception occured: {ex.Message}"); } return(rtnResponse); }
private static async void Send(bpDevice targetDevice, string function, string requestBody = "") { // Posts a message to the device endpoint directly WebRequest request = WebRequest.Create($"https://api.particle.io/v1/devices/{targetDevice.deviceId}/{function}?access_token={targetDevice.accessToken}"); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; Stream dataStream = request.GetRequestStream(); byte[] requestbody = Encoding.UTF8.GetBytes($"args={requestBody}"); dataStream.Write(requestbody, 0, requestbody.Length); dataStream.Close(); WebResponse response = await request.GetResponseAsync(); response.Close(); }
/// <summary> /// Registers a new device, returns true if successful. Won't allow an add if it already exists or a game is running /// </summary> /// <param name="newDevice"></param> /// <returns></returns> public bool RegisterDevice(bpDevice newDevice) { bool resultValue = false; if (!this.IsRunning) // if a game isn't currently running // add the device if its not already in the list { if (!GameState.Exists(i => i.deviceId == newDevice.deviceId)) { GameState.Add(newDevice); this.SaveState(); resultValue = true; } } return(resultValue); }
public async static Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "put", Route = "pong")] HttpRequestMessage req, TraceWriter log) { log.Info("Pong recieved from device."); HttpResponseMessage rtnResponse = null; try { // Get request body, should contain deviceId and accessToken bpPong pongData = await req.Content.ReadAsAsync <bpPong>(); log.Info($"Pong received from device {pongData.deviceId}."); GameStateManager gameState = new GameStateManager(); // get game state if (gameState.IsRunning) // if game isn't running { if (pongData.success == false) // last device failed to respond in time, remove it { gameState.RemoveDevice(pongData.deviceId); } // select next device to ping and prepare response (-1 if this is the last device, aka the winner) bpDevice randomDevice = gameState.GetRandomDevice(); log.Info($"Sending initial ping to device {randomDevice.deviceId}."); SendToDevice.Ping(randomDevice, (gameState.DeviceCount > 1 ? 5000 : -1)); if (gameState.DeviceCount <= 1) // game is over, stop game { gameState.StopGame(); } } // respond to request rtnResponse = req.CreateResponse(HttpStatusCode.OK); } catch (RuntimeBinderException ex) { // "name property doesn't exist in request body rtnResponse = req.CreateResponse(HttpStatusCode.BadRequest, @"Please pass the device ID and status of the 'ping' in the body of your request: { ""deviceID"" : ""value"", ""status"" : true|false }"); } return(rtnResponse); }
public async static Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "put", Route = "game")] HttpRequestMessage req, TraceWriter log) { log.Info("StartGame received a request."); HttpResponseMessage rtnResponse = req.CreateResponse(HttpStatusCode.OK); // we'll only do this if we're not already doing start notifications if (notificationTask == null || notificationTask.Status != TaskStatus.Running) { GameStateManager gameState = new GameStateManager(); // get game state if (!gameState.IsRunning) // if game isn't running { List <bpDevice> deviceList = gameState.GetDeviceList(); // if we have more than 1 device if (deviceList.Count > 1) { gameState.StartGame(); // start device notification background task notificationTask = new Task(() => { log.Info("StartGame: Starting device notification."); // get list of devices pingTasks = new List <Task>(); foreach (bpDevice device in deviceList) { pingTasks.Add(Task.Run(() => { log.Info($"StartGame: Notifying device {device.deviceId} of start."); SendToDevice.Start(device); })); } Task.WaitAll(pingTasks.ToArray()); Thread.Sleep(3000); // wait three seconds after all pings are complete bpDevice randomDevice = gameState.GetRandomDevice(); log.Info($"StartGame: Sending initial ping to device {randomDevice.deviceId}."); SendToDevice.Ping(randomDevice, 5000); }); // spin off a thread to send the pings in the background so we can return immediately to caller notificationTask.Start(); } else { log.Info($"StartGame: Only one device. Don't you have any friends?"); } } else { log.Info("StartGame: Game already running. So I'm going to ignore this."); } } else { log.Info("StartGame: Notifications currently running. So I'm going to ignore this."); } return(rtnResponse); }
/// <summary> /// Sends a start signal to a device /// </summary> /// <param name="targetDevice"></param> public static void Start(bpDevice targetDevice) { Send(targetDevice, "startGame"); }
/// <summary> /// Sends a ping event /// </summary> /// <param name="deviceToPing">the device ID and access token for the target device</param> /// <param name="value">the timeout value</param> public static void Ping(bpDevice deviceToPing, int value) { Send(deviceToPing, "ping", value.ToString()); }