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 =
|
||||
| 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 {
|
||||
let partOfDay = state.PartOfDay
|
||||
|
||||
match event with
|
||||
| ReceivedZigbeeEvent payload ->
|
||||
let! zigbeeEvent = parseZigbeeEvent payload
|
||||
|
||||
return
|
||||
state,
|
||||
match zigbeeEvent with
|
||||
| DeviceAnnounce friendlyName ->
|
||||
let maybeLight = tryFindLight friendlyName
|
||||
|
|
@ -35,5 +40,6 @@ let onEventReceived (partOfDay: PartOfDay) (event: Event) =
|
|||
match maybeLight with
|
||||
| Some light -> generateZigbeeCommandToFixLight partOfDay light |> Seq.singleton
|
||||
| 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.Text
|
||||
open System.Threading
|
||||
open System.Threading.Tasks
|
||||
open Microsoft.Extensions.Logging
|
||||
open MQTTnet
|
||||
|
|
@ -35,24 +36,32 @@ let private publishZigbeeCommands (mqttClient: IMqttClient) (logger: ILogger) (c
|
|||
|> Async.Ignore
|
||||
}
|
||||
|
||||
let private handleEvent (mqttClient: IMqttClient) (logger: ILogger) (partOfDay: PartOfDay) (event: Event) =
|
||||
let commandsResult = event |> onEventReceived partOfDay
|
||||
let private handleEvent (mqttClient: IMqttClient) (logger: ILogger) (state: State) (event: Event) =
|
||||
let result = event |> onEventReceived state
|
||||
|
||||
match commandsResult with
|
||||
| Ok commands -> publishZigbeeCommands mqttClient logger commands
|
||||
| Error UnknownType -> async.Return()
|
||||
match result with
|
||||
| Ok(newState, commands) ->
|
||||
async {
|
||||
do! publishZigbeeCommands mqttClient logger commands
|
||||
return newState
|
||||
}
|
||||
| Error UnknownType -> async.Return state
|
||||
| Error e ->
|
||||
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 decodedPayload = Encoding.UTF8.GetString(&payload)
|
||||
|
||||
logger.LogInformation("Received message with payload {Payload}", decodedPayload)
|
||||
|
||||
ReceivedZigbeeEvent decodedPayload
|
||||
|> handleEvent mqttClient logger (getPartOfDay DateTime.Now)
|
||||
ReceivedZigbeeEvent decodedPayload |> handleEvent mqttClient logger state
|
||||
|
||||
[<EntryPoint>]
|
||||
let mainAsync _ =
|
||||
|
|
@ -76,8 +85,19 @@ let mainAsync _ =
|
|||
|
||||
let mqttClientOptions = MqttClientOptionsBuilder().WithTcpServer(server).Build()
|
||||
|
||||
let stateLock = new SemaphoreSlim(1, 1)
|
||||
let mutable state = { PartOfDay = getPartOfDay DateTime.Now }
|
||||
|
||||
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
|
||||
:> Task)
|
||||
|
||||
|
|
@ -94,7 +114,13 @@ let mainAsync _ =
|
|||
let currentPartOfDay = getPartOfDay DateTime.Now
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue