Skip to content

Commit

Permalink
Handle arm and defence mode commands sent to cameras
Browse files Browse the repository at this point in the history
  • Loading branch information
duanemck committed Mar 30, 2022
1 parent 263e8fd commit 8578b4d
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 23 deletions.
4 changes: 4 additions & 0 deletions ezviz-cli/ezviz-cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.8.0" />
</ItemGroup>

</Project>
11 changes: 8 additions & 3 deletions ezviz-mqtt-systemd/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
"connectRetries": 3,
"connectRetryDelaySeconds": 60,
"topics": {
"command": "ezviz/cmnd/{serial}",
"command": "ezviz/cmnd/{serial}/#",
"status": "ezviz/stat/{serial}",
"alarm": "ezviz/alarm/{serial}",
"lwt": "ezviz/lwt/{serial}"
}
"lwt": "ezviz/lwt/{serial}",
"globalCommand": "ezviz/cmnd/global/#",
"globalStatus": "ezviz/stat/global/{command}"
},
"serviceLwtTopic": "ezviz/lwt",
"serviceLwtOfflineMessage": "OFF",
"serviceLwtOnlineMessage": "ON"
},
"json": {
"serializeBooleans": 1,
Expand Down
11 changes: 8 additions & 3 deletions ezviz-mqtt-windows-service/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
"connectRetries": 3,
"connectRetryDelaySeconds": 60,
"topics": {
"command": "ezviz/cmnd/{serial}",
"command": "ezviz/cmnd/{serial}/#",
"status": "ezviz/stat/{serial}",
"alarm": "ezviz/alarm/{serial}",
"lwt": "ezviz/lwt/{serial}"
}
"lwt": "ezviz/lwt/{serial}",
"globalCommand": "ezviz/cmnd/global/#",
"globalStatus": "ezviz/stat/global/{command}"
},
"serviceLwtTopic": "ezviz/lwt",
"serviceLwtOfflineMessage": "OFF",
"serviceLwtOnlineMessage": "ON"
},
"json": {
"serializeBooleans": 1,
Expand Down
109 changes: 93 additions & 16 deletions ezviz-mqtt/MqttPublisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using ezviz.net.domain;
using ezviz.net.exceptions;
using ezviz_mqtt.config;
using ezviz_mqtt.util;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Text;
Expand Down Expand Up @@ -86,18 +87,35 @@ public async Task Init()
}
}

private void SendRetainedMqtt(string topicKey, string? serial, object data, bool jsonSerialize = true)

private void SendMqttForCamera(string topicKey, string? serial, object data, bool retain = false)
{
if (serial == null)
{
throw new ArgumentNullException(nameof(serial));
}
var topic = mqttConfig.Topics[topicKey].Replace("{serial}", serial);
SendMqtt(topic, data, retain);
}

private void SendLwtForService(string message)
{
SendMqtt(topicKey, serial, data, true, jsonSerialize);
var topic = mqttConfig.ServiceLwtTopic;
SendMqtt(topic, message, true, false);
}

private void SendMqtt(string topicKey, string? serial, object data, bool retain = false, bool jsonSerialize = true)
private void SendLwtForCamera(string? serial, string message)
{
if (serial == null)
{
throw new ArgumentNullException(nameof(serial));
}
var topic = mqttConfig.Topics[topicKey].Replace("{serial}", serial);
var topic = mqttConfig.Topics["lwt"].Replace("{serial}", serial);
SendMqtt(topic, message, true, false);
}

private void SendMqtt(string topic, object data, bool retain = false, bool jsonSerialize = true)
{
#pragma warning disable IL2026
var dataString = jsonSerialize ? JsonSerializer.Serialize(data, jsonSerializationOptions) : data.ToString();
#pragma warning restore IL2026
Expand Down Expand Up @@ -141,6 +159,10 @@ public async Task PublishAsync(CancellationToken stoppingToken)

private async Task PollCameras(CancellationToken stoppingToken)
{
logger.LogInformation("Checking Defence Mode");
var defenceMode = await ezvizClient.GetDefenceMode();
SendMqtt(mqttConfig.Topics["globalStatus"].Replace("{command}", MQTT_COMMAND_DEFENCEMODE), defenceMode.ToString(), false, false);

logger.LogInformation("Polling ezviz API for full camera details");
cameras = await ezvizClient.GetCameras(stoppingToken);

Expand All @@ -150,8 +172,8 @@ private async Task PollCameras(CancellationToken stoppingToken)
{
return;
}
SendMqtt("status", camera.SerialNumber, camera);
SendRetainedMqtt("lwt", camera.SerialNumber, (camera.Online ?? false) ? "ON" : "OFF", false);
SendMqttForCamera("status", camera.SerialNumber, camera);
SendLwtForCamera(camera.SerialNumber, (camera.Online ?? false) ? "ON" : "OFF");
}
logger.LogInformation("Polling done, published details of {0} cameras", cameras.Count());
}
Expand Down Expand Up @@ -185,7 +207,7 @@ private async Task PollAlarms(CancellationToken stoppingToken)
{
logger.LogInformation($"New alarm found [{alarm.AlarmId}]");
alarm.DownloadedPicture = await ezvizClient.GetAlarmImageBase64(alarm);
SendMqtt("alarm", camera.SerialNumber, alarm);
SendMqttForCamera("alarm", camera.SerialNumber, alarm);
}
}
else
Expand Down Expand Up @@ -219,25 +241,80 @@ private void ConnectToMqtt()
{
logger.LogInformation("Connecting to MQTT {0}", mqttConfig.Host);
mqttClient.MqttMsgPublishReceived += MessageReceived;
if (string.IsNullOrEmpty(mqttConfig.Username))
{
mqttClient.Connect("ezviz.net");
}
else
{
mqttClient.Connect("ezviz.net", mqttConfig.Username, mqttConfig.Password);
}

var commandTopic = mqttConfig.Topics["command"].Replace("{serial}", "#");
mqttClient.Connect("ezviz.net", mqttConfig.Username, mqttConfig.Password, false, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, true, mqttConfig.ServiceLwtTopic, mqttConfig.ServiceLwtOfflineMessage, false, 60);
SendLwtForService(mqttConfig.ServiceLwtOnlineMessage);


var commandTopic = mqttConfig.Topics["command"].Replace("{serial}", "+");
logger.LogInformation("Subscribing to {0}", commandTopic);
mqttClient.Subscribe(new[] { commandTopic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });

commandTopic = mqttConfig.Topics["globalCommand"];
logger.LogInformation("Subscribing to {0}", commandTopic);
mqttClient.Subscribe(new[] { commandTopic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });

}

private void MessageReceived(object sender, MqttMsgPublishEventArgs e)
{
string utfString = Encoding.UTF8.GetString(e.Message, 0, e.Message.Length);
logger.LogInformation($"Received message via MQTT from [{e.Topic}] => {utfString}");

if (e.Topic.StartsWith(mqttConfig.Topics["globalCommand"].Replace("/#", "")))
{
Task.WaitAll(HandleGlobalCommand(e.Topic, utfString));
}
else
{
Task.WaitAll(HandleCameraCommand(e.Topic, utfString));
}
}

private async Task HandleCameraCommand(string topic, string message)
{
string command = topic.Substring(topic.LastIndexOf("/") + 1);
string topicWithoutCommand = topic.Replace($"/{command}", "");
string serial = topicWithoutCommand.Substring(topicWithoutCommand.LastIndexOf("/") + 1);

//TODO: Clean this up
switch (command)
{
case MQTT_COMMAND_ARMED:
var camera = cameras.FirstOrDefault(c => c.SerialNumber == serial);
if (camera != null)
{
if (message == "ON")
{
await camera.Arm();
}
else if (message == "OFF")
{
await camera.Disarm();
}
}
break;
default:
logger.LogInformation($"Unknown MQTT command received {command}");
break;
}
}

private const string MQTT_COMMAND_DEFENCEMODE = "defenceMode";
private const string MQTT_COMMAND_ARMED = "armed";

private async Task HandleGlobalCommand(string topic, string message)
{
string command = topic.Substring(topic.LastIndexOf("/") + 1);
switch (command)
{
case MQTT_COMMAND_DEFENCEMODE:
await ezvizClient.SetDefenceMode(EnumX.Parse<DefenceMode>(message));
break;
default:
logger.LogInformation($"Unknown MQTT command received {command}");
break;
}
}

public void Dispose()
Expand Down
4 changes: 4 additions & 0 deletions ezviz-mqtt/config/MqttOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ internal class MqttOptions

public int ConnectRetryDelaySeconds { get; set; }

public string ServiceLwtTopic { get; set; } = null!;
public string ServiceLwtOfflineMessage { get; set; } = null!;
public string ServiceLwtOnlineMessage { get; set; } = null!;

public IDictionary<string, string> Topics { get; set; } = null!;
}

2 changes: 1 addition & 1 deletion ezviz.net/IEzvizApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Task<GenericResponse> ChangeSwitch(string serialNumber,
Task <SetDefenceModeResponse> SetDefenceMode(
[Body(BodySerializationMethod.UrlEncoded)] Dictionary<string, object> data);

[Post("/v3/userdevices/v1/group/defenceMode?groupId=-1")]
[Get("/v3/userdevices/v1/group/defenceMode?groupId=-1")]
Task<GetDefenceModeResponse> GetDefenceMode();

[Put("/v3/devices/{deviceSerial}/{channel}/changeDefenceStatusReq")]
Expand Down

0 comments on commit 8578b4d

Please sign in to comment.