IPHostEntry host;
string localIP = "1";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
localIP = ip.ToString();
localIP = localIP.Substring(localIP.LastIndexOf(".") + 1);
}
}
Program.Setup(() => {
Program
.AddControlWidget("homegenie/generic/status")
.AddOption("ClientId", "hg-" + localIP, "0. Enter unique ID for this client", "text")
.AddOption("ServerAddress", "", "1. MQTT server address", "text")
.AddOption("ServerPort", "1883", "2. MQTT server port", "text")
.AddOption("TLS", "", "3. Connect using TLS/SSL", "checkbox")
.AddOption("WebSockets", "", "4. Connect using WebSockets", "checkbox")
.AddOption("ServerTopic", "#", "5. Topic", "text")
.AddOption("Username", "", "6. Username (optional)", "text")
.AddOption("Password", "", "7. Password (optional)", "text")
.AddFeature("", "", "MQTT.SensorPublish", "Publish this module events", "checkbox");
});
Program.Run();
string server = Program.Option("ServerAddress").Value.Trim();
int port = 1883; int.TryParse(Program.Option("ServerPort").Value, out port);
string topic = Program.Option("ServerTopic").Value.Trim();
string clientid = Program.Option("ClientId").Value.Trim();
string username = Program.Option("Username").Value.Trim();
string password = Program.Option("Password").Value.Trim();
bool useWebSockets = Program.Option("WebSockets").Value == "On" ? true : false;
bool useTls = Program.Option("TLS").Value == "On" ? true : false;
//----------
int mRX = 0;
int mTX = 0;
string mACT = "";
Program.AddVirtualModule("statusdisplay.MQTT-status", "1", "Generic", "homegenie/generic/status");
var moduleST1 = Modules.InDomain("statusdisplay.MQTT-status").WithAddress("1").Get();
Program.RaiseEvent(moduleST1, "StatusWidget.MQTT", "Off", ":nopopup:"); mACT = "Off";
Program.RaiseEvent(moduleST1, "StatusWidget.Receive", mRX.ToString(), ":nopopup:");
Program.RaiseEvent(moduleST1, "StatusWidget.Transmit", mTX.ToString(), ":nopopup:");
//----------
var MqttIsConnected = false;
MqttClient.Reset();
//----------
//Program.RaiseEvent(moduleST1, "StatusWidget.MQTT", "On", ":nopopup:"); mACT = "On";
//----------
if (server == "")
{
Program.Notify("Please configure server address");
Pause(5);
return;
}
MqttClient.Subscribe(topic, (mtopic, bytespayload) => {
var parts = mtopic.Split('/');
var cid = parts[0];
//
if (parts.Length == 4)
{
try
{
var domain = parts[1];
var address = parts[2];
var type = parts[3];
// convert binary message to string
string mpayload = Encoding.UTF8.GetString(bytespayload);
var module = Modules.InDomain("MQTT:" + cid + "." + domain).WithAddress(address).Get();
switch (type)
{
case "command":
if (domain == "MQTT.Listeners" && address == clientid)
{
var cmdobj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(mpayload);
var targetmodule = Modules.InDomain(cmdobj.Domain.ToString()).WithAddress(cmdobj.Address.ToString());
if (targetmodule.Get().Instance != null)
{
string command = cmdobj.Command.ToString();
switch (command)
{
case "Module.Describe":
var modinstance = targetmodule.Get().Instance;
MqttClient.Publish(clientid + "/" + modinstance.Domain + "/" + modinstance.Address + "/description", Service.Utility.Module2Json(modinstance, false));
break;
default:
targetmodule.Command(command).Execute();
break;
}
}
}
break;
case "description":
if (cid != clientid && module.Instance != null)
{
var modobj = Newtonsoft.Json.JsonConvert.DeserializeObject<Module>(mpayload);
module.Instance.Name = modobj.Name;
module.Instance.Description = modobj.Description;
module.Instance.DeviceType = modobj.DeviceType;
var parentid = module.Parameter("VirtualModule.ParentId").Value;
module.Instance.Properties = modobj.Properties;
module.Parameter("VirtualModule.ParentId").Value = parentid;
module.Parameter("MQTT.SourceNode").Value = cid;
Program.Notify("Created remote module " + module.Instance.Domain + " " + module.Instance.Address);
}
break;
case "event":
if (cid != clientid)
{
var property = Newtonsoft.Json.JsonConvert.DeserializeObject<ModuleParameter>(mpayload);
if (module.Instance == null)
{
Program.AddVirtualModule("MQTT:" + cid + "." + domain, address, "Sensor", "");
module = Modules.InDomain("MQTT:" + cid + "." + domain).WithAddress(address).Get();
}
else if (!module.HasParameter("MQTT.SourceNode"))
{
MqttClient.Publish(clientid + "/MQTT.Listeners/" + cid + "/command", "{ 'Domain': " + "'" + domain + "', 'Address' : '" + address + "', 'Command' : 'Module.Describe' }");
}
module.RaiseEvent(property.Name, property.Value, ":nopopup:");
//----------
mRX++;
//----------
}
break;
}
} catch (Exception e) {
Program.Notify("ERROR: " + e.Message);
MqttIsConnected = false;
}
}
//Console.WriteLine("MQTT {0} : {1}", mtopic, mpayload);
});
When.WebServiceCallReceived("MQTT:", ( args ) => {
string[] reqs = ((string)args).Split('/');
string domain = reqs[0];
string address = reqs[1];
var commands = new List<string>(reqs);
// remove domain and address to obtain the command parts only
commands.RemoveAt(0); commands.RemoveAt(0);
string command = String.Join("/", commands.ToArray());
try
{
int mqttend = domain.IndexOf(".");
int mqttdel = domain.IndexOf(":");
var mqttdest = domain.Substring(mqttdel + 1, mqttend - mqttdel - 1);
domain = domain.Substring(mqttend + 1);
MqttClient.Publish(clientid + "/MQTT.Listeners/" + mqttdest + "/command", "{ 'Domain': " + "'" + domain + "', 'Address' : '" + address + "', 'Command' : '" + command + "' }");
//----------
mRX++;
Program.RaiseEvent(moduleST1, "StatusWidget.Receive", mRX.ToString(), ":nopopup:");
//----------
return new ResponseText("OK");
}
catch (Exception e) {
Program.Notify("ERROR: " + e.Message);
MqttIsConnected = false;
}
return new ResponseText("ERROR");
});
// We want to do further processing whenever a module changes
When.ModuleParameterChanged( (module, property) => {
if (module.HasFeature("MQTT.SensorPublish") && (property.Name.StartsWith("Sensor.") || property.Name.StartsWith("Status.") || property.Name.StartsWith("Meter.")) && !module.Instance.Domain.StartsWith("MQTT:"))
{
try{
byte[] bytes = Encoding.Default.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(property));
string payload = Encoding.UTF8.GetString(bytes);
MqttClient.Publish(clientid + "/" + module.Instance.Domain + "/" + module.Instance.Address + "/event", Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(property)));
//----------
mTX++;
//----------
}
catch (Exception e){
Program.Notify("ERROR: " + e.Message);
MqttIsConnected = false;
}
}
// returning true, will route event to other listeners
return true;
});
while (Program.IsRunning) {
Program.RaiseEvent(moduleST1, "StatusWidget.Receive", mRX.ToString(), ":nopopup:");
Program.RaiseEvent(moduleST1, "StatusWidget.Transmit", mTX.ToString(), ":nopopup:");
if (!MqttIsConnected) {
MqttIsConnected = true;
Program.Notify("Connecting to '" + server + ":" + port + "' ...");
try
{
if (username != "")
{
MqttClient.WithCredentials(username, password);
}
MqttClient
.Service(server)
.UsingWebSockets(useWebSockets)
.WithTls(useTls)
.Connect(port, clientid, (connected)=>{
MqttIsConnected = connected;
if (connected) {
Program.Notify("Connected!");
//----------
Program.RaiseEvent(moduleST1, "StatusWidget.MQTT", "On", ":nopopup:"); mACT = "On";
//----------
} else {
Program.Notify("Disconnected!");
//----------
Program.RaiseEvent(moduleST1, "StatusWidget.MQTT", "Off", ":nopopup:"); mACT = "Off";
MqttClient.Reset();
//----------
}
});
}
catch (Exception e)
{
Program.Notify(e.Message);
Pause(5);
return;
}
}
Pause(30);
}
[]
HomeAutomation.HomeGenie.Automation
77
MQTT Network
Share modules with other HomeGenie servers connected to the same MQTT network.
Other servers will automatically inherit the published module once an event is generated from it.
Interconnections
checkbox
MQTT.SensorPublish
Publish this module events
true
2022-08-16T15:26:05.829475Z
2022-08-16T15:26:06.218978Z
CSharp
true