Added NightAlert project for travel kit

This commit is contained in:
2021-06-10 14:39:06 -04:00
commit d38d9e3b7e
308 changed files with 35922 additions and 0 deletions

View File

@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Odbc;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using NightScout.Interfaces;
using NightscoutLibrary.Configuration;
using Quobject.EngineIoClientDotNet.Client.Transports;
using Quobject.SocketIoClientDotNet.Client;
namespace NightScout
{
public class NightscoutDataSource : INightscoutDataSource
{
public Socket Socket { get; set; }
public Manager Manager { get; set; }
public log4net.ILog Logger { get; set; }
public IRaspberryPiButtonSource ButtonSource { get; set; }
public INightscoutAlertConfiguration NightscoutAlertConfiguration { get; set; }
public event Action Connected;
public event Action<Object> DataUpdate;
public event Action<Object> SocketError;
public event Action<Object> Alarm;
public event Action<Object> UrgentAlarm;
public event Action<Object> ClearAlarm;
public event Action StaleDataAlarm;
private DateTime lastDataUpdate = DateTime.Now;
private DateTime lastSgvReading = DateTime.Now;
public NightscoutDataSource(INightscoutAlertConfiguration configuration, log4net.ILog logger)
{
Logger = logger;
NightscoutAlertConfiguration = configuration;
ResetManagerAndConnect();
PrepareSocketEvents();
}
public NightscoutDataSource(INightscoutAlertConfiguration configuration, log4net.ILog logger, IRaspberryPiButtonSource buttonSource)
: this(configuration, logger)
{
ButtonSource = buttonSource;
ButtonSource.ButtonStateChange += ButtonSource_ButtonStateChange;
}
public void Emit(String eventName, String data)
{
Socket.Emit(eventName, data);
}
public void Emit(String eventName, JObject data)
{
Socket.Emit(eventName,data);
}
public virtual void Authorize()
{
JObject authRequest = new JObject {{"client", "web"}};
Socket.Emit("authorize", authRequest);
}
public virtual void ClearAlerts()
{
Logger.Info("Sending Clear Alerts Message");
Socket.Emit("ack", 2, "default", 45 * 60 * 1000);
Logger.Debug("Sent ack");
}
protected virtual void OnConnect()
{
Logger.Info("Connected to Socket.IO endpoint");
if (Connected != null)
Connected();
}
protected virtual void OnDataUpdate(object data)
{
Logger.DebugFormat("Data Update: {0}", data);
if (DataUpdate != null)
DataUpdate(data);
//Update lastUpdated
JObject dataUpdate = JObject.Parse(data.ToString());
if (dataUpdate["lastUpdated"] != null)
{ //lastUpdated is in ms
Int32 lastUpdatedUnixTime = (Int32)(dataUpdate["lastUpdated"].ToObject<Int64>() / 1000);
lastDataUpdate = UnixTimeStampToDateTime(lastUpdatedUnixTime);
Logger.InfoFormat("Last data update reset to {0}", lastDataUpdate);
}
if (dataUpdate["sgvs"] != null)
{
var sgvs = dataUpdate["sgvs"].Children();
var newestSSgv =
sgvs.Where(sgv => sgv["mills"] != null).OrderByDescending(sgv => sgv["mills"].Value<Int64>()).First();
Int64 sgvReadTime = newestSSgv["mills"].Value<Int64>();
DateTime reading = UnixTimeStampToDateTime(sgvReadTime / 1000);;
if (reading > lastSgvReading)
lastSgvReading = reading;
if(newestSSgv["mgdl"] != null)
Logger.InfoFormat("New sgv read of {0} mg/dl on {1}", newestSSgv["mgdl"], lastSgvReading);
}
}
protected virtual void OnSocketError(object error)
{
//Socket.Close();
Logger.InfoFormat("Socket Error: {0}", error);
if (SocketError != null)
SocketError(error);
}
protected virtual void OnAlarm(object alarm)
{
Logger.InfoFormat("Alarm: {0}", alarm);
if (Alarm != null)
Alarm(alarm);
}
protected virtual void OnUrgentAlarm(object alarm)
{
Logger.InfoFormat("Urgent Alarm: {0}", alarm);
if (UrgentAlarm != null)
UrgentAlarm(alarm);
}
protected virtual void OnClearAlarm(object alarm)
{
Logger.InfoFormat("Clear Alarm: {0}", alarm);
if (ClearAlarm != null)
ClearAlarm(alarm);
}
protected virtual void OnStaleDataAlarm()
{
if (StaleDataAlarm != null)
StaleDataAlarm();
}
protected void ResetManagerAndConnect()
{
//, DisablePing = true, Transports = new List<string>() { "polling" }
Options options;
options = new IO.Options();
Manager = new Manager(new Uri(NightscoutAlertConfiguration.NightscoutBaseURL), options);
Socket = Manager.Socket("/"); //IO.Socket(configuration.NightscoutBaseURL, options);
}
private void HeartbeatThread()
{
while (true)
{
//30 minutes - (currentTime - lastDataUpdate)
const double millisecondsToSleep = (5*60*1000); //(30*60*1000) - (DateTime.Now - lastDataUpdate).TotalMilliseconds;
Thread.Sleep((Int32)millisecondsToSleep);
if ((DateTime.Now - lastDataUpdate).TotalMinutes >= 20)
{ //forcefully reset data connection
Logger.Info("Data update timeout, closing socket");
Manager.EngineSocket.Close();
lastDataUpdate = DateTime.Now;
}
if ((DateTime.Now - lastSgvReading).TotalMinutes >= 30)
{ //Stale data alarm
OnStaleDataAlarm();
Logger.Info("Data stale alarm");
lastSgvReading = DateTime.Now;
}
}
}
private void PrepareSocketEvents()
{
Socket.On(Socket.EVENT_CONNECT, OnConnect);
Socket.On(Socket.EVENT_ERROR, OnSocketError);
Socket.On("dataUpdate", OnDataUpdate);
Socket.On("alarm", OnAlarm);
Socket.On("urgent_alarm", OnUrgentAlarm);
Socket.On("clear_alarm", OnClearAlarm);
Manager.On(Manager.EVENT_CONNECT_ERROR, (err) => Logger.InfoFormat("EVENT_CONNECT_ERROR: {0}",err));
Manager.On(Manager.EVENT_ERROR, (err) => Logger.InfoFormat("EVENT_ERROR: {0}", err));
Manager.On(Manager.EVENT_RECONNECT_ERROR, (err) => Logger.InfoFormat("EVENT_RECONNECT_ERROR: {0}", err));
Manager.On(Manager.EVENT_RECONNECT_FAILED, () => Logger.Info("EVENT_RECONNECT_FAILED"));
Manager.On(Manager.EVENT_CLOSE, (reason) => Logger.InfoFormat("EVENT_CLOSE: {0}", reason));
Task.Factory.StartNew(HeartbeatThread,TaskCreationOptions.LongRunning);
}
private void ButtonSource_ButtonStateChange(bool obj)
{
if (obj)
{ //Button pressed, STOP active alerts
ClearAlerts();
}
}
private static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
// Unix timestamp is seconds past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime;
}
}
}