using System; using System.Collections.Generic; using System.Text; using System.Text.Json; namespace ESPServer { /* * Описание параметра, который может придти от юнита */ class UnitValue { // Название параметра public string name; // Текущее значение public float value; // Сдвиг адреса, по которому это значение будет храниться в modbus public int addressOffset; } /* * Описание конкретного модуля (релейный, датчик, whatever) */ class Unit { // Айдишник юнита (мак-адрес) public string id; // Название (для генерации конфигов например) public string name; // Базовый адрес в модбасе public int baseAddress; // Значения которые есть в юните public Dictionary values; // текущий IP юнита public string ip; public UnitValue GetValue(string name) { if (!values.ContainsKey(name)) { return null; } return values[name]; } public int MinOffset { get { int min = int.MaxValue; foreach (var u in values) if (u.Value.addressOffset < min) min = u.Value.addressOffset; return min; } } public int MaxOffset { get { int max = int.MinValue; foreach (var u in values) if (u.Value.addressOffset > max) max = u.Value.addressOffset; return max; } } } class UnitsDatabase { List units; public UnitsDatabase(JsonElement config) { units = new List(); foreach (var unitConfig in config.EnumerateArray()) { var u = new Unit(); u.id = unitConfig.GetProperty("id").GetString(); u.name = unitConfig.GetProperty("name").GetString(); u.baseAddress = unitConfig.GetProperty("address").GetInt32(); u.values = new Dictionary(); foreach (var knownValue in unitConfig.GetProperty("values").EnumerateArray()) { var uv = new UnitValue(); uv.name = knownValue.GetProperty("name").GetString(); uv.addressOffset = knownValue.GetProperty("offset").GetInt32(); u.values[uv.name] = uv; } units.Add(u); } } internal Unit AddUnit(string id) { lock (units) { var u = new Unit(); u.id = id; u.name = id; u.baseAddress = -1; u.values = new Dictionary(); units.Add(u); return u; } } internal Dictionary GetUnitIPs() { var result = new Dictionary(); lock (units) { foreach (var u in units) { if (!string.IsNullOrEmpty(u.ip)) { result[u.id] = u.ip; } } } return result; } public Unit GetUnit(string id) { lock (units) { foreach (var u in units) { if (u.id == id) return u; } } return null; } #region OpenHAB config generation internal void GenerateItemsConfig(StringBuilder config) { foreach (var u in units) { foreach (var uv in u.values) { var v = uv.Value; config.Append(string.Format("Number {0}_{1} \"{0} {1}\"", u.name, v.name)); config.Append(" {channel=\""); config.AppendFormat("modbus:data:esp_server:esp_server:"); config.AppendFormat("{0}_{1}:number", u.name, v.name); config.Append("\"}\n"); } } } internal void GenerateThingsConfig(StringBuilder config) { int minAddress = int.MaxValue; int maxAddress = int.MinValue; foreach (var u in units) { if (u.baseAddress + u.MinOffset < minAddress) { minAddress = u.baseAddress + u.MinOffset; } if (u.baseAddress + u.MaxOffset > maxAddress) { maxAddress = u.baseAddress + u.MaxOffset; } } // поскольку читаем флоаты, нужен ещё регистр запаса maxAddress++; config.Append("\tBridge poller "); config.Append("esp_server"); config.AppendFormat("[start = {0}, length = {1}, type = \"holding\", refresh = 500] {{\n", minAddress, maxAddress - minAddress + 1); foreach (var u in units) { foreach (var uv in u.values) { var v = uv.Value; config.Append("\t\tThing data "); config.Append(u.name + "_" + v.name); config.AppendFormat("[readStart = \"{0}\", readValueType = \"float32\"]\n", u.baseAddress + v.addressOffset); } } config.Append("\t}\n"); } #endregion } }