private async Task <WebSocketWrapper> ConnectWebSocket()
 {
     return(await WebSocketWrapper
            .Create(uri)
            .OnConnect(async(wsw) =>
     {
         connected = true;
         // send hello to initiate protocol
         await wsw.SendMessageAsync($"{{ \"id\": {++id}, \"type\": \"hello\", \"version\": \"2\"}}");
         // subscribe to settings
         await SendSubscriptionRequest(wsw, settingsPath);
     })
            .OnDisconnect((wsw) =>
     {
         connected = false;
         return Task.CompletedTask;
     })
            .OnMessage(async(message, wsw) => await MessageReceived(message, wsw).ConfigureAwait(false))
            .ConnectAsync());
 }
        public Task Start(CancellationToken cancellationToken)
        {
            return(Task.Run(async() =>
            {
                try
                {
                    webSocketWrapper = await ConnectWebSocket();
                }
                catch (Exception e)
                {
                    // todo log error
                    logger.LogError(e, e.Message);
                }

                while (!cancellationToken.IsCancellationRequested)
                {
                    if (!connected)
                    {
                        try
                        {
                            webSocketWrapper = await ConnectWebSocket();
                        }
                        catch (Exception e)
                        {
                            // todo log error
                            logger.LogDebug(e.Message);
                        }
                    }

                    Thread.Sleep(10);
                }

                if (connected)
                {
                    webSocketWrapper.Disconnect();
                }
            }));
        }
        // handle messages received from websocket
        private async Task MessageReceived(string message, WebSocketWrapper webSocketWrapper)
        {
            if (!string.IsNullOrEmpty(message))
            {
                var messageObject = JObject.Parse(message);

                if (messageObject["type"].ToString() == "ping")
                {
                    // ping received as heartbeat, reply with a ping
                    await SendPing(webSocketWrapper).ConfigureAwait(false);
                }
                else if (messageObject["type"].ToString() == "pub")
                {
                    // message from one of the subscriptions, see if it is a setting
                    if (messageObject["path"].ToString() == settingsPath)
                    {
                        var settings = messageObject["message"];

                        foreach (var key in settings.Children())
                        {
                            var property = key as JProperty;

                            if (property != null)
                            {
                                var handled = false;
                                var name    = property.Name;
                                var setting = settingsToSendThrough.FirstOrDefault(s => s.SettingKey == name);

                                if (setting != null)
                                {
                                    object propertyValue = property.Value.ToObject(setting.SettingType);
                                    this.Settings.AddOrUpdate(name, propertyValue, (name, value) => propertyValue);

                                    if (name == "RA")
                                    {
                                        alarmThread.ResetAlarm();
                                        handled = true;
                                    }
                                    else if (name == "MT")
                                    {
                                        alarmThread.AlarmMuted = (int)propertyValue > 0;

                                        // we are only allowed to mute for one minute
                                        if ((int)propertyValue > 0)
                                        {
                                            muteResetCancellationTokenSource.Cancel();
                                            muteResetCancellationTokenSource = new CancellationTokenSource();
                                            var cancellationToken = muteResetCancellationTokenSource.Token;

                                            _ = Task.Run(async() =>
                                            {
                                                await Task.Delay(60000);

                                                if (!cancellationToken.IsCancellationRequested)
                                                {
                                                    logger.LogInformation("Resetting the mute state to zero");
                                                    await this.apiService.SendSettingToServerAsync("MT", 0);
                                                }
                                            }, muteResetCancellationTokenSource.Token);
                                        }
                                    }
                                    else if (name == "ACTIVE" && (int)propertyValue == 1)
                                    {
                                        _ = Task.Run(() =>
                                        {
                                            // ACTIVE changed to 1, play short beep
                                            logger.LogInformation("Received setting from server: {0}={1}", name, propertyValue);
                                            var bytes = setting.ToBytes(propertyValue);

                                            serialThread.WriteData(bytes, (messageId) =>
                                            {
                                                logger.LogDebug("The machine should have played a beep after receiving active 1");
                                                serialThread.PlayBeep();
                                                alarmThread.ResetAlarm();
                                                alarmThread.SetInactive();
                                                return(Task.CompletedTask);
                                            });
                                        });

                                        handled = true;

                                        serialThread.MachineState = (int)propertyValue;
                                    }
                                    else if (name == "ACTIVE")
                                    {
                                        LastSettingReceivedAt = DateTime.Now;

                                        _ = Task.Run(() =>
                                        {
                                            logger.LogInformation("Received setting from server: {0}={1}", name, propertyValue);
                                            var bytes = setting.ToBytes(propertyValue);
                                            serialThread.WriteData(bytes);

                                            alarmThread.ResetAlarm();
                                            alarmThread.SetInactive();
                                        });
                                        handled = true;

                                        serialThread.MachineState = (int)propertyValue;
                                    }

                                    if (!handled && setting.SendToArduino)
                                    {
                                        LastSettingReceivedAt = DateTime.Now;
                                        _ = Task.Run(() =>
                                        {
                                            logger.LogInformation("Received setting from GUI/server: {0}={1}", name, propertyValue);
                                            var bytes = setting.ToBytes(propertyValue);
                                            serialThread.WriteData(bytes, (msgId) =>
                                            {
                                                logger.LogInformation("Received setting ack from machine: {0}={1}", name, propertyValue);
                                                return(Task.CompletedTask);
                                            });
                                        });

                                        if (setting.CausesAlarmInactivity)
                                        {
                                            alarmThread.SetInactive();
                                        }
                                    }
                                } // end if setting != null
                            }     // end if property != null
                        }         // end foreach
                    }
                }
            }
        }
 private async Task SendSubscriptionRequest(WebSocketWrapper webSocketWrapper, string path)
 {
     await webSocketWrapper.SendMessageAsync($"{{ \"id\": {++id}, \"type\": \"sub\", \"path\": \"{path}\"}}").ConfigureAwait(false);
 }
 private async Task SendPing(WebSocketWrapper webSocketWrapper)
 {
     await webSocketWrapper.SendMessageAsync($"{{ \"id\": {++id}, \"type\": \"ping\"}}").ConfigureAwait(false);
 }
Пример #6
0
        // handle messages received from websocket
        private async Task MessageReceived(string message, WebSocketWrapper webSocketWrapper)
        {
            if (!string.IsNullOrEmpty(message))
            {
                var messageObject = JObject.Parse(message);

                if (messageObject["type"].ToString() == "ping")
                {
                    // ping received as heartbeat, reply with a ping
                    await SendPing(webSocketWrapper).ConfigureAwait(false);
                }
                else if (messageObject["type"].ToString() == "pub")
                {
                    // message from one of the subscriptions, see if it is a setting
                    if (messageObject["path"].ToString() == settingsPath)
                    {
                        var settings = messageObject["message"];

                        foreach (var key in settings.Children())
                        {
                            var property = key as JProperty;

                            if (property != null)
                            {
                                var name          = property.Name;
                                var propertyValue = property.Value.ToObject <float>();
                                this.Settings[name] = propertyValue;

                                if (name == "RA")
                                {
                                    alarmThread.ResetAlarm();
                                }
                                else if (name == "MT")
                                {
                                    alarmThread.AlarmMuted = propertyValue > 0.0f;

                                    // we are only allowed to mute for one minute
                                    if (propertyValue > 0.0f)
                                    {
                                        muteResetCancellationTokenSource.Cancel();
                                        muteResetCancellationTokenSource = new CancellationTokenSource();
                                        var cancellationToken = muteResetCancellationTokenSource.Token;

                                        _ = Task.Run(async() =>
                                        {
                                            await Task.Delay(60000);

                                            if (!cancellationToken.IsCancellationRequested)
                                            {
                                                logger.LogInformation("Resetting the mute state to zero");
                                                await this.apiService.SendSettingToServerAsync("MT", 0);
                                            }
                                        }, muteResetCancellationTokenSource.Token);
                                    }
                                }
                                else if (name == "ACTIVE" && propertyValue >= 0.9f && propertyValue < 1.1f) // see if float value is close to 1
                                {
                                    _ = Task.Run(() =>
                                    {
                                        // ACTIVE changed to 1, play short beep
                                        logger.LogInformation("Received setting from server: {0}={1}", name, propertyValue);
                                        var bytes = ASCIIEncoding.ASCII.GetBytes(string.Format("{0}={1}", name, propertyValue.ToString("0.00")));

                                        serialThread.WriteData(bytes, (messageId) =>
                                        {
                                            logger.LogDebug("The machine should have played a beep after receiving active 1");
                                            serialThread.PlayBeep();
                                            alarmThread.ResetAlarm();
                                            alarmThread.SetInactive();
                                            return(Task.CompletedTask);
                                        });
                                    });
                                }
                                else if (name == "ACTIVE")
                                {
                                    LastSettingReceivedAt = DateTime.Now;

                                    _ = Task.Run(() =>
                                    {
                                        logger.LogInformation("Received setting from server: {0}={1}", name, propertyValue);
                                        var bytes = ASCIIEncoding.ASCII.GetBytes(string.Format("{0}={1}", name, propertyValue.ToString("0.00")));
                                        serialThread.WriteData(bytes);

                                        alarmThread.ResetAlarm();
                                        alarmThread.SetInactive();
                                    });
                                }

                                var setting = settingsToSendThrough.FirstOrDefault(s => s.SettingKey == name);
                                if (setting != null)
                                {
                                    LastSettingReceivedAt = DateTime.Now;
                                    _ = Task.Run(() =>
                                    {
                                        logger.LogInformation("Received setting from server: {0}={1}", name, propertyValue);
                                        var bytes = ASCIIEncoding.ASCII.GetBytes(string.Format("{0}={1}", name, propertyValue.ToString("0.00")));
                                        serialThread.WriteData(bytes);
                                    });

                                    if (setting.CausesAlarmInactivity)
                                    {
                                        alarmThread.SetInactive();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }