Introduce a State object instead of passing in partOfDay
We'll have some more complicated use cases for this later.
This commit is contained in:
parent
eebd72f40c
commit
e226d092d8
2 changed files with 46 additions and 14 deletions
|
|
@ -19,15 +19,20 @@ let internal generateZigbeeCommandToFixLight partOfDay light =
|
||||||
|
|
||||||
type Event =
|
type Event =
|
||||||
| ReceivedZigbeeEvent of payload: string
|
| ReceivedZigbeeEvent of payload: string
|
||||||
| PartOfDayChanged
|
| PartOfDayChanged of newPartOfDay: PartOfDay
|
||||||
|
|
||||||
let onEventReceived (partOfDay: PartOfDay) (event: Event) =
|
type State = { PartOfDay: PartOfDay }
|
||||||
|
|
||||||
|
let onEventReceived (state: State) (event: Event) =
|
||||||
result {
|
result {
|
||||||
|
let partOfDay = state.PartOfDay
|
||||||
|
|
||||||
match event with
|
match event with
|
||||||
| ReceivedZigbeeEvent payload ->
|
| ReceivedZigbeeEvent payload ->
|
||||||
let! zigbeeEvent = parseZigbeeEvent payload
|
let! zigbeeEvent = parseZigbeeEvent payload
|
||||||
|
|
||||||
return
|
return
|
||||||
|
state,
|
||||||
match zigbeeEvent with
|
match zigbeeEvent with
|
||||||
| DeviceAnnounce friendlyName ->
|
| DeviceAnnounce friendlyName ->
|
||||||
let maybeLight = tryFindLight friendlyName
|
let maybeLight = tryFindLight friendlyName
|
||||||
|
|
@ -35,5 +40,6 @@ let onEventReceived (partOfDay: PartOfDay) (event: Event) =
|
||||||
match maybeLight with
|
match maybeLight with
|
||||||
| Some light -> generateZigbeeCommandToFixLight partOfDay light |> Seq.singleton
|
| Some light -> generateZigbeeCommandToFixLight partOfDay light |> Seq.singleton
|
||||||
| None -> Seq.empty
|
| None -> Seq.empty
|
||||||
| PartOfDayChanged -> return lights |> Seq.map (generateZigbeeCommandToFixLight partOfDay)
|
| PartOfDayChanged newPartOfDay ->
|
||||||
|
return { PartOfDay = newPartOfDay }, lights |> Seq.map (generateZigbeeCommandToFixLight partOfDay)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
open System
|
open System
|
||||||
open System.Text
|
open System.Text
|
||||||
|
open System.Threading
|
||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
open MQTTnet
|
open MQTTnet
|
||||||
|
|
@ -35,24 +36,32 @@ let private publishZigbeeCommands (mqttClient: IMqttClient) (logger: ILogger) (c
|
||||||
|> Async.Ignore
|
|> Async.Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
let private handleEvent (mqttClient: IMqttClient) (logger: ILogger) (partOfDay: PartOfDay) (event: Event) =
|
let private handleEvent (mqttClient: IMqttClient) (logger: ILogger) (state: State) (event: Event) =
|
||||||
let commandsResult = event |> onEventReceived partOfDay
|
let result = event |> onEventReceived state
|
||||||
|
|
||||||
match commandsResult with
|
match result with
|
||||||
| Ok commands -> publishZigbeeCommands mqttClient logger commands
|
| Ok(newState, commands) ->
|
||||||
| Error UnknownType -> async.Return()
|
async {
|
||||||
|
do! publishZigbeeCommands mqttClient logger commands
|
||||||
|
return newState
|
||||||
|
}
|
||||||
|
| Error UnknownType -> async.Return state
|
||||||
| Error e ->
|
| Error e ->
|
||||||
logger.LogError("Error {Error} while {Event}", e, event)
|
logger.LogError("Error {Error} while {Event}", e, event)
|
||||||
async.Return()
|
async.Return state
|
||||||
|
|
||||||
let private onMqttMessageReceived (mqttClient: IMqttClient) (logger: ILogger) (message: MqttApplicationMessage) =
|
let private onMqttMessageReceived
|
||||||
|
(mqttClient: IMqttClient)
|
||||||
|
(logger: ILogger)
|
||||||
|
(state: State)
|
||||||
|
(message: MqttApplicationMessage)
|
||||||
|
=
|
||||||
let payload = message.Payload
|
let payload = message.Payload
|
||||||
let decodedPayload = Encoding.UTF8.GetString(&payload)
|
let decodedPayload = Encoding.UTF8.GetString(&payload)
|
||||||
|
|
||||||
logger.LogInformation("Received message with payload {Payload}", decodedPayload)
|
logger.LogInformation("Received message with payload {Payload}", decodedPayload)
|
||||||
|
|
||||||
ReceivedZigbeeEvent decodedPayload
|
ReceivedZigbeeEvent decodedPayload |> handleEvent mqttClient logger state
|
||||||
|> handleEvent mqttClient logger (getPartOfDay DateTime.Now)
|
|
||||||
|
|
||||||
[<EntryPoint>]
|
[<EntryPoint>]
|
||||||
let mainAsync _ =
|
let mainAsync _ =
|
||||||
|
|
@ -76,8 +85,19 @@ let mainAsync _ =
|
||||||
|
|
||||||
let mqttClientOptions = MqttClientOptionsBuilder().WithTcpServer(server).Build()
|
let mqttClientOptions = MqttClientOptionsBuilder().WithTcpServer(server).Build()
|
||||||
|
|
||||||
|
let stateLock = new SemaphoreSlim(1, 1)
|
||||||
|
let mutable state = { PartOfDay = getPartOfDay DateTime.Now }
|
||||||
|
|
||||||
mqttClient.add_ApplicationMessageReceivedAsync (fun e ->
|
mqttClient.add_ApplicationMessageReceivedAsync (fun e ->
|
||||||
onMqttMessageReceived mqttClient logger e.ApplicationMessage
|
async {
|
||||||
|
do! stateLock.WaitAsync() |> Async.AwaitTask
|
||||||
|
|
||||||
|
try
|
||||||
|
let! newState = onMqttMessageReceived mqttClient logger state e.ApplicationMessage
|
||||||
|
state <- newState
|
||||||
|
finally
|
||||||
|
stateLock.Release() |> ignore
|
||||||
|
}
|
||||||
|> Async.StartAsTask
|
|> Async.StartAsTask
|
||||||
:> Task)
|
:> Task)
|
||||||
|
|
||||||
|
|
@ -94,7 +114,13 @@ let mainAsync _ =
|
||||||
let currentPartOfDay = getPartOfDay DateTime.Now
|
let currentPartOfDay = getPartOfDay DateTime.Now
|
||||||
|
|
||||||
if previousPartOfDay <> Some currentPartOfDay then
|
if previousPartOfDay <> Some currentPartOfDay then
|
||||||
do! PartOfDayChanged |> handleEvent mqttClient logger currentPartOfDay
|
do! stateLock.WaitAsync() |> Async.AwaitTask
|
||||||
|
|
||||||
|
try
|
||||||
|
let! newState = PartOfDayChanged currentPartOfDay |> handleEvent mqttClient logger state
|
||||||
|
state <- newState
|
||||||
|
finally
|
||||||
|
stateLock.Release() |> ignore
|
||||||
|
|
||||||
previousPartOfDay <- Some currentPartOfDay
|
previousPartOfDay <- Some currentPartOfDay
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue