public Node(string hwid, IServiceProvider services, IConfiguration configuration) : base(services) { this.mqtt = GetService <mqtt.Service>(); this.configuration = configuration; using (var db = new SensorCloudContext(configuration)) node = db.nodes.Include(node => node.Room).Include(node => node.sensors).First(n => n.hwid == hwid); mqtt.On("(" + node.Room.topic + "/" + node.topic + ")/(.*)", onData); }
private void onData(Match match, string payload) { if (match.Groups[2].Value == "ping") { dynamic data = JObject.Parse(payload); Ping ping = new Ping() { stamp = DateTime.Now, nodeid = node.id, ip = data.ip, heapspace = data.heapspace, rssi = data.rssi }; using (var db = new SensorCloudContext(configuration)) { db.pings.Add(ping); db.SaveChanges(); } lastPing = DateTime.Now; } if (match.Groups[2].Value == "temperature" || match.Groups[2].Value == "humidity") { if (payload == "0") { return; } try { SensorData sensorData = new SensorData() { stamp = DateTime.Now, nodeid = node.id, type = match.Groups[2].Value, value = float.Parse(payload) }; using (var db = new SensorCloudContext(configuration)) { db.sensordata.Add(sensorData); db.SaveChanges(); } lastValue = DateTime.Now; } catch (FormatException) { Log("Error while parsing payload"); } } if (match.Groups[2].Value == "alive") { if (payload == "dead") { Log("Node is dead, removing from listening list"); mqtt.Un("(" + node.Room.topic + "/" + node.topic + ")/(.*)"); Dispose(); //TODO: check } } }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { mqtt = GetService <mqtt.Service>(); db = new SensorCloudContext(configuration); foreach (var item in db.dashboardItems.ToList()) { if (item.type == "mqtt") { StartMqtt(item); } } await update(); }
public void TestFirst() { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddJsonFile(Path.GetFullPath("../../../../appsettings.json")); //ewww IConfiguration configuration = builder.Build(); SensorCloud.services.dash.Config config = new SensorCloud.services.dash.Config(); configuration.GetSection("Dashboard").Bind(config); var db = new SensorCloudContext(configuration); var service = new SensorCloud.services.dash.Service(null, configuration, config); service.handleSshCommand(db.dashboardItems.First(i => i.type == "sshcommand")); }
protected override Task ExecuteAsync(CancellationToken stoppingToken) { Engine.init(this); using (SensorCloudContext db = new SensorCloudContext(configuration)) { rules = new List <Rule>(); db.rules.Where(r => r.enabled == 1).ToList().ForEach(r => rules.Add(new Rule() { engine = new Engine(r.data), name = r.name, id = r.id })); } UpdateLists(); return(Task.CompletedTask); }
private async Task SenseDeviceCount() { using (SensorCloudContext db = new SensorCloudContext(configuration)) { var deviceCount = (JObject)(await session.getApi("api/system/device_count")); int max = 0; db.sensordata.Add(new SensorData() { stamp = DateTime.Now, nodeid = 0, type = "NetworkClients", value = (int)deviceCount["ActiveDeviceNumbers"] }); db.sensordata.Add(new SensorData() { stamp = DateTime.Now, nodeid = 0, type = "NetworkWired", value = (int)deviceCount["LanActiveNumber"] }); var wifiWizard = (JArray)(await session.getApi("api/system/wizard_wifi")); if (wifiWizard.Count > 0) { max = wifiWizard.Max(w => (int)w["Numbers"]); db.sensordata.Add(new SensorData() { stamp = DateTime.Now, nodeid = 0, type = "NetworkWifi", value = max }); } await db.SaveChangesAsync(); if (mqtt != null) { await mqtt.Publish("network/clients", (int)deviceCount["ActiveDeviceNumbers"] + ""); await mqtt.Publish("network/clients/wired", (int)deviceCount["LanActiveNumber"] + ""); await mqtt.Publish("network/clients/wifi", max + ""); } }//using }
public void ReloadRule(int id) { Log($"Reloading rule {id}"); using (SensorCloudContext db = new SensorCloudContext(configuration)) { rules.RemoveAll(r => r.id == id); var rule = db.rules.FirstOrDefault(r => r.id == id && r.enabled == 1); if (rule != null) { rules.Add(new Rule() { engine = new Engine(rule.data), name = rule.name, id = rule.id }); } } UpdateLists(); }
protected override Task ExecuteAsync(CancellationToken stoppingToken) { using (db = new SensorCloudContext(configuration)) { Dictionary <DateTime, DataPacket> measurementLookup = new Dictionary <DateTime, DataPacket>(); db.sensordata .Where(d => d.nodeid == 0 && (d.type == "power1" || d.type == "power2" || d.type == "gas")) .OrderByDescending(d => d.id) .Take(10000) .ToList().ForEach(m => { if (!measurementLookup.ContainsKey(m.stamp)) { measurementLookup[m.stamp] = new DataPacket(); } if (m.type == "gas") { measurementLookup[m.stamp].GasUsage = (Decimal)m.value; } if (m.type == "power1") { measurementLookup[m.stamp].PowerConsumptionTariff1 = (Decimal)m.value; } if (m.type == "power2") { measurementLookup[m.stamp].PowerConsumptionTariff2 = (Decimal)m.value; } }); measurementLookup.Where(k => k.Value.IsValid).ToList().ForEach(k => measurements.Add(new Measurement() { time = k.Key, data = k.Value })); measurements.Sort((m1, m2) => m1.time.CompareTo(m2.time)); } meter = new SmartMeter(); meter.OnData += OnData; meter.Connect(config.serial); return(Task.CompletedTask); }
private async Task BackLog() { while (true) { await Task.Delay(1000 * 60 * 30); using (var db2 = new SensorCloudContext(configuration)) { Log("Updating backlog"); await db2.Database.ExecuteSqlCommandAsync("REPLACE INTO `sensordata.hourly` (`stamp`, `nodeid`, `type`, `value`) SELECT DATE_FORMAT(`stamp`, '%Y-%m-%d %H:00:00') as `date`, `nodeid`, `type`, round(avg(`value`), 2) FROM `sensordata` WHERE `type` = 'TEMPERATURE' OR `type` = 'HUMIDITY' GROUP BY `nodeid`, `type`, `date`"); await db2.Database.ExecuteSqlCommandAsync("REPLACE INTO `sensordata.daily` (`stamp`, `nodeid`, `type`, `value`) SELECT DATE_FORMAT(`stamp`, '%Y-%m-%d') as `date`, `nodeid`, `type`, round(avg(`value`), 2) FROM `sensordata` WHERE `type` = 'TEMPERATURE' OR `type` = 'HUMIDITY' GROUP BY `nodeid`, `type`, `date`"); await db2.Database.ExecuteSqlCommandAsync("REPLACE INTO `sensordata.weekly` (`year`, `week`, `nodeid`, `type`, `value`) SELECT year(`stamp`) as `year`, week(`stamp`) as `week`,`nodeid`, `type`, round(avg(`value`), 2) FROM `sensordata.daily` WHERE `type` = 'TEMPERATURE' OR `type` = 'HUMIDITY' GROUP BY `nodeid`, `type`, `stamp`, `year`, `week`"); await db2.Database.ExecuteSqlCommandAsync("REPLACE INTO `sensordata.monthly` (`year`, `month`, `nodeid`, `type`, `value`) SELECT year(`stamp`) as `year`, month(`stamp`) as `month`,`nodeid`, `type`, round(avg(`value`), 2) FROM `sensordata.daily` WHERE `type` = 'TEMPERATURE' OR `type` = 'HUMIDITY' GROUP BY `nodeid`, `type`, `year`, `month`"); //aggregration for power/gas await db2.Database.ExecuteSqlCommandAsync("REPLACE INTO `sensordata.hourly` (`stamp`, `nodeid`, `type`, `value`) SELECT DATE_FORMAT(`stamp`, '%Y-%m-%d %H:00:00') as `date`, `nodeid`, `type`, max(`value`) - min(`value`) as `value` FROM `sensordata` WHERE `type` = 'power1' OR `type` = 'power2' OR `type` = 'gas' GROUP BY `nodeid`, `type`, `date`"); Log("Done updating backlog"); } } }
private async Task CheckNewHosts() { List <Host> currentHosts = await GetHosts(); using (SensorCloudContext db = new SensorCloudContext(configuration)) { var dbHosts = db.HG569_hosts.ToList(); foreach (var host in currentHosts) { if (dbHosts.Any(h => h.hostname == host.HostName && h.ip == host.IPAddress && h.mac == host.MACAddress)) { continue; } var dbHost = dbHosts.FirstOrDefault(h => h.mac == host.MACAddress); if (dbHost == null) { await db.HG569_hosts.AddAsync(dbHost = new HG659_host() { mac = host.MACAddress, hostname = host.HostName, ip = host.IPAddress }); if (mqtt != null) { await mqtt.Publish("network/newhost", JObject.FromObject(dbHost).ToString()); } } else { if (dbHost.hostname != host.HostName) { Console.WriteLine($"hostname changed for mac {host.MACAddress}, host {host.HostName}"); if (mqtt != null) { await mqtt.Publish("network/hostchange", JObject.FromObject(new { ip = dbHost.ip, mac = dbHost.mac, oldHost = dbHost.hostname, newHost = host.HostName }).ToString()); } } if (dbHost.ip != host.IPAddress) { Console.WriteLine($"IP address changed for mac {host.MACAddress}, host {host.HostName}"); if (mqtt != null) { await mqtt.Publish("network/ipchange", JObject.FromObject(new { oldIp = dbHost.ip, newIp = host.IPAddress, mac = dbHost.mac, host = dbHost.hostname }).ToString()); } } dbHost.ip = host.IPAddress; dbHost.hostname = host.HostName; } } await db.SaveChangesAsync(); } }
public RoomController(SensorCloudContext db, services.rulemanager.Service rulesManager) { this.db = db; }
public SpotnetController(SensorCloudContext db, services.spotnet.Config config) { this.db = db; this.config = config; }
public NodesController(SensorCloudContext db) { this.db = db; }
public Func <Reply> showSensorData(string timeSpan, int timeOffset, string value, List <datamodel.Node> nodes) { return(() => { var colors = new Color[] { Color.Red, Color.Green, Color.Blue, Color.DarkViolet, Color.Salmon, Color.PowderBlue, Color.GreenYellow, Color.DarkOrange }; var colorLookup = new Dictionary <int, Color>(); var title = ""; if (nodes.Count == 0) { return "No nodes"; } var nodesIn = string.Join(",", nodes.Select(n => n.id)); var between = $"addtime(CURDATE(), '23:59:59') - interval {1+timeOffset} day AND addtime(CURDATE(), '23:59:59') - interval {timeOffset} day"; var table = ""; var type = "TEMPERATURE"; var valueName = "`value`"; var groupby = ""; var config = new Graph.Config(); switch (value) { case "temperature": config.min = 0; config.max = 30; type = "TEMPERATURE"; title = "Temperature "; break; case "humidity": config.min = 0; config.max = 100; type = "HUMIDITY"; title = "Humidity "; break; case "power": config.min = 0; config.max = 1; type = "power1' OR `type` = 'power2"; //ewww groupby = "GROUP BY `stamp`"; valueName = "SUM(`value`)"; title = "Power "; nodesIn = "0"; break; case "gas": config.min = 0; config.max = 1; type = "gas"; title = "Gas "; nodesIn = "0"; break; } switch (timeSpan) { case "day": config.markerCount = 24; config.markerMod = 4; config.markerFunc = (e) => $"{(e * 4):00}:00"; // between = $"addtime(CURDATE(), '23:59:59') - interval {1 + timeOffset} day AND addtime(CURDATE(), '23:59:59') - interval {timeOffset} day"; title += " day graph for " + DateTime.Now.Subtract(TimeSpan.FromDays(timeOffset)).ToString("dddd, dd MMMM yyyy") + " (" + timeOffset + " days ago)"; if (value == "power" || value == "gas") { table = ".hourly"; } break; case "week": config.markerCount = 7 * 4; config.markerMod = 4; config.markerFunc = (e) => e < 7 ? (((DayOfWeek)e).ToString() + " " + DateTime.Now.Subtract(TimeSpan.FromDays((int)DateTime.Now.DayOfWeek - e + 7 * timeOffset)).Day + " - " + DateTime.Now.Subtract(TimeSpan.FromDays((int)DateTime.Now.DayOfWeek - e + 7 * timeOffset)).Month) : ""; table = ".hourly"; between = $"addtime(SUBDATE(CURDATE(), 1+WEEKDAY(CURDATE())), '00:00:00') - interval {timeOffset} week AND addtime(SUBDATE(CURDATE(), 1+WEEKDAY(CURDATE())), '00:00:00') - interval {(timeOffset-1)} week"; title += " week graph for " + timeOffset + " weeks ago"; break; case "month": config.markerCount = 31; //TODO config.markerMod = 7; config.markerFunc = (e) => $"{e*7+1}"; table = ".daily"; between = $"addtime(SUBDATE(CURDATE(), DAYOFMONTH(CURDATE())), '23:59:59') - interval {timeOffset} month AND addtime(SUBDATE(CURDATE(), DAYOFMONTH(CURDATE())), '23:59:59') - interval {(timeOffset - 1)} month"; title += " month graph for " + DateTime.Now.AddMonths(-timeOffset).ToString("MMMM"); break; } string sql = $"SELECT `id`, `stamp`, `nodeid`, `type`, {valueName} as `value` " + $"FROM `sensordata{table}` " + $"WHERE (`type` = '{type}') AND `stamp` BETWEEN {between} AND " + $"`nodeid` IN ({nodesIn}) " + groupby + $"ORDER BY `stamp`"; Console.WriteLine(sql); #pragma warning disable EF1000 // Possible SQL injection vulnerability. List <SensorData> sensorData; using (var db = new SensorCloudContext(configuration)) sensorData = db.sensordata.FromSql(sql).OrderBy(d => d.stamp).ToList(); #pragma warning restore EF1000 // Possible SQL injection vulnerability. if (sensorData.Count == 0) { return "No data found"; } foreach (var d in sensorData) { if (!colorLookup.ContainsKey(d.nodeid)) { colorLookup[d.nodeid] = colors[colorLookup.Count]; config.values[colorLookup[d.nodeid]] = new List <KeyValuePair <float, float> >(sensorData.Count / nodes.Count); } if (timeSpan == "day") { config.values[colorLookup[d.nodeid]].Add(new KeyValuePair <float, float>(d.stamp.Hour + d.stamp.Minute / 60.0f, (float)d.value)); } if (timeSpan == "week") { config.values[colorLookup[d.nodeid]].Add(new KeyValuePair <float, float>(4 * ((int)d.stamp.DayOfWeek + d.stamp.Hour / 24.0f), (float)d.value)); } if (timeSpan == "month") { config.values[colorLookup[d.nodeid]].Add(new KeyValuePair <float, float>((int)d.stamp.Day - 1, (float)d.value)); } } var image = Graph.buildImage(config); return new Reply() { message = title, image = image }; }); }
private async void OnData(object sender, DataPacket data) { measurements.Add(new Measurement() { data = data, time = DateTime.Now }); while (measurements.Count > 0 && measurements[0].time.AddMinutes(60 * 24) < DateTime.Now) { measurements.RemoveAt(0); } status["p1meter"] = $"Valid: {data.IsValid}"; using (db = new SensorCloudContext(configuration)) { db.sensordata.Add(new SensorData() { stamp = DateTime.Now, nodeid = 0, type = "power1", value = (double)data.PowerConsumptionTariff1 }); db.sensordata.Add(new SensorData() { stamp = DateTime.Now, nodeid = 0, type = "power2", value = (double)data.PowerConsumptionTariff2 }); db.sensordata.Add(new SensorData() { stamp = DateTime.Now, nodeid = 0, type = "gas", value = (double)data.GasUsage }); await db.SaveChangesAsync(); } if (mqtt != null) { var values = new Dictionary <String, int> { { "1m", 1 }, { "10m", 10 }, { "1h", 60 }, { "24h", 60 * 24 }, }; if (measurements.Count > 0) { foreach (var v in values) { DataPacket firstValue = measurements.AsEnumerable().Reverse().TakeWhile(m => m.time.AddMinutes(v.Value) >= DateTime.Now).Last().data; decimal power = (data.PowerConsumptionTariff1 - firstValue.PowerConsumptionTariff1) + (data.PowerConsumptionTariff2 - firstValue.PowerConsumptionTariff2); decimal gas = data.GasUsage - firstValue.GasUsage; await mqtt.Publish($"p1/use/{v.Key}/power", power + ""); await mqtt.Publish($"p1/use/{v.Key}/gas", gas + ""); } } await mqtt.Publish("p1/power1", data.PowerConsumptionTariff1 + ""); await mqtt.Publish("p1/power2", data.PowerConsumptionTariff2 + ""); await mqtt.Publish("p1/power", data.PowerConsumptionTariff1 + data.PowerConsumptionTariff2 + ""); await mqtt.Publish("p1/gas", data.GasUsage + ""); } }
public SensorDataController(SensorCloudContext db) { this.db = db; }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { try { while (true) { Spotnet spotnet = new Spotnet(config.host, config.port, config.user, config.pass); await spotnet.Connect(); spotnet.OnSpot += async(s, spot) => { using (SensorCloudContext db = new SensorCloudContext(configuration)) { Log($"Saving {spot.article}"); datamodel.Spot dbSpot = new datamodel.Spot() { article = spot.article, articleid = spot.articleid, cat = spot.cat, desc = spot.desc, posted = spot.posted, size = spot.size, subcat = spot.subcat, title = spot.title, nzbs = spot.segments.Select(seg => new datamodel.SpotNzb() { article = spot.article, articleid = spot.articleid, segment = seg }).ToList() }; db.spots.Add(dbSpot); db.spotNzbs.AddRange(dbSpot.nzbs); await db.SaveChangesAsync(); if (mqtt != null) { await mqtt.Publish("spotnet", JObject.FromObject(new { id = spot.articleid, title = spot.title }).ToString()); } } }; long min = spotnet.GroupInfo.low; using (SensorCloudContext db = new SensorCloudContext(configuration)) { try { min = db.spots.Max(e => e.article) + 1; } catch (Exception e) { Console.WriteLine(e); } } await spotnet.Update(min); spotnet.Disconnect(); await Task.Delay(60000 * 5); } } catch (Exception e) { Console.WriteLine("Exception thrown in spotnet"); Console.WriteLine(e); } }
public DashController(SensorCloudContext db) { this.db = db; }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { mqtt = GetService <mqtt.Service>(); db = new SensorCloudContext(configuration); //TODO: move to a construction using 'using' keyword var ruleManager = GetService <rulemanager.Service>(); ruleManager.AddFunction(new Function() { Module = this.moduleNameFirstCap, FunctionName = "Activate", Parameters = new List <Tuple <string, rules.Socket> >() { new Tuple <string, rules.Socket>("nodeid", new rules.NumberSocket()) }, Callback = this.Activate }); mqtt.On("boot/whoami$", async(match, message) => { dynamic data = JObject.Parse(message); String hwid = data.hwid; var ret = db.nodes.Where(n => n.hwid == hwid).Select(n => new { id = n.id, hwid = n.hwid, name = n.name, topic = n.topic, room = n.roomId, config = JsonConvert.DeserializeObject(n.config), roomtopic = n.Room.topic, sensors = n.sensors.Select(s => new { id = s.id, nodeid = s.nodeid, type = s.type, config = JsonConvert.DeserializeObject(s.config) }) }).First(); await mqtt.Publish("boot/whoami/" + hwid, JsonConvert.SerializeObject(ret)); Log($"Sensor {ret.name} (id {ret.id}) in {ret.roomtopic} is booting"); var newNode = new Node(hwid, services, configuration); if (nodes.Any(n => n.hwid == hwid)) { Log($"Sensor already connected before"); nodes.RemoveAll(n => n.hwid == hwid); } nodes.Add(newNode); }); mqtt.On("boot/whoami/(.+)", (match, message) => { }); var watchDog = Task.Run(WatchDog); var backlog = Task.Run(BackLog); await Task.WhenAll(new Task[] { watchDog, backlog }); }