diff --git a/README.md b/README.md index b0e4322..de3e173 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Fake pod implementation * This version also mimics a behavior we see in some DASH pods where the pod disconnects every 3 minutes; this can be used with iOS hooks to make a heartbeat to run Loop in situations where a BLE CGM is not available. -* It serves a control panel at http://:8080/ (`-api` changes the address): the pod's reservoir, delivery, age, alerts and fault, with controls to set the reservoir and pod age, raise alerts, trigger or clear a fault, and crash on the next command to test unacknowledged commands. The panel drives a JSON API: `GET /status`, and `POST /command` with `{"command": "changeReservoir", "value": 45}` (also `setActiveTime` in minutes, `setAlerts` as a slot mask, `setFault` with a fault code, 0 to clear, and `crashNextCommand` with `"beforeProcessing": true|false`). +* It serves a control panel at http://:8080/ (`-api` changes the address): the pod's reservoir, delivery, age, alerts and fault, with controls to set the reservoir and pod age, raise alerts, trigger or clear a fault, and crash on the next command to test unacknowledged commands. The panel drives a JSON API: `GET /status`, and `POST /command` with `{"command": "changeReservoir", "value": 45}` (also `setActiveTime` in minutes, `setAlerts` as a slot mask, `setFault` with a fault code, 0 to clear, `crashNextCommand` with `"beforeProcessing": true|false`, and `ignoreNextMessages` with a count, which keeps the link up but leaves that many messages unanswered, as a pod that didn't hear them would). * The websocket API at `/ws`, used by the separate [NodeJS/React frontend](https://github.com/ps2/pod_simulator_frontend), is still there. diff --git a/pkg/api/server.go b/pkg/api/server.go index a2cffd5..9749839 100644 --- a/pkg/api/server.go +++ b/pkg/api/server.go @@ -173,6 +173,11 @@ func (s *Server) handleCommand(bytes []byte) error { return err } s.pod.SetActiveTime(int(value)) + case "ignoreNextMessages": + if err := needValue("message count", 0, 100); err != nil { + return err + } + s.pod.IgnoreNextMessages(int(value)) case "crashNextCommand": beforeProcessing, ok := msg["beforeProcessing"].(bool) if !ok { diff --git a/pkg/pod/pod.go b/pkg/pod/pod.go index 22add65..5f5bc21 100644 --- a/pkg/pod/pod.go +++ b/pkg/pod/pod.go @@ -47,6 +47,7 @@ type Pod struct { // Once one of these are set, the next command will crash the executable. var crashBeforeProcessingCommand bool var crashAfterProcessingCommand bool +var ignoreMessages int func New(ble *bluetooth.Ble, state *PODState) *Pod { ret := &Pod{ @@ -338,6 +339,17 @@ func (p *Pod) CommandLoop(pMsg PodMsgBody) { } log.Tracef("pkg pod; got command message: %s", spew.Sdump(msg)) + p.mtx.Lock() + ignore := ignoreMessages > 0 + if ignore { + ignoreMessages-- + } + p.mtx.Unlock() + if ignore { + log.Infof("pkg pod; ignoring message seq %d (ignoreNextMessages)", msg.SequenceNumber) + continue + } + if msg.SequenceNumber == lastMsgSeq { // this is a retry because we did not answer yet // ignore duplicate commands/mesages @@ -835,6 +847,14 @@ func (p *Pod) SetActiveTime(newVal int) { p.mtx.Unlock() } +// IgnoreNextMessages makes the pod stay connected but not answer the next +// count messages, as a pod that didn't hear them would. +func (p *Pod) IgnoreNextMessages(count int) { + p.mtx.Lock() + ignoreMessages = count + p.mtx.Unlock() +} + func (p *Pod) CrashNextCommand(beforeProcessing bool) { p.mtx.Lock() if beforeProcessing {