Possibility to filter by ChangeType
This commit is contained in:
parent
079e32e893
commit
ab5bd412f2
45
README.md
45
README.md
|
@ -13,6 +13,51 @@ I didn't even test it yet so no idea if it works
|
|||
$ TELEGRAM_APITOKEN=YOUR_API_TOKEN ./alarm_bot --satel_addr=127.0.0.1 --satel_port=31337 --tg_chat_id=YOUR_CHAT_ID_FROM_BOTFATHER
|
||||
```
|
||||
|
||||
### Filtering events by change type
|
||||
|
||||
It's possible to filter events by change type. Use the `--allowed-types=TYPE1,TYPE2,...` command line parameter to do that. If that parameter is not provided, then all change types are allowed, otherwise only the provided ones will be used for notifications.
|
||||
|
||||
Supported types are:
|
||||
- `zone-violation`
|
||||
- `zone-tamper`
|
||||
- `zone-alarm`
|
||||
- `zone-tamper-alarm`
|
||||
- `zone-alarm-memory`
|
||||
- `zone-tamper-alarm-memory`
|
||||
- `zone-bypass`
|
||||
- `zone-no-violation-trouble`
|
||||
- `zone-long-violation-trouble`
|
||||
- `armed-partition-suppressed`
|
||||
- `armed-partition`
|
||||
- `partition-armed-mode-2`
|
||||
- `partition-armed-mode-3`
|
||||
- `partition-with-1st-code-enter`
|
||||
- `partition-entry-time`
|
||||
- `partition-exit-time-over-10s`
|
||||
- `partition-exit-time-under-10s`
|
||||
- `partition-temporary-blocked`
|
||||
- `partition-blocked-guard-round`
|
||||
- `partition-alarm`
|
||||
- `partition-fire-alarm`
|
||||
- `partition-alarm-memory`
|
||||
- `partition-fire-alarm-memory`
|
||||
- `output`
|
||||
- `doors-opened`
|
||||
- `doors-opened-long`
|
||||
- `status-bit`
|
||||
- `trouble-part-1`
|
||||
- `trouble-part-2`
|
||||
- `trouble-part-3`
|
||||
- `trouble-part-4`
|
||||
- `trouble-part-5`
|
||||
- `trouble-memory-part-1`
|
||||
- `trouble-memory-part-2`
|
||||
- `trouble-memory-part-3`
|
||||
- `trouble-memory-part-4`
|
||||
- `trouble-memory-part-5`
|
||||
- `partition-with-violated-zones`
|
||||
- `zone-isolate`
|
||||
|
||||
## Debugging
|
||||
|
||||
Set the `OMIT_TG` environment variable to, well, omit sending anything over to Telegram and just see the logs instead.
|
||||
|
|
28
filters.go
28
filters.go
|
@ -13,17 +13,27 @@ import (
|
|||
func FilterByType(ev <-chan satel.Event, allowedTypes []satel.ChangeType) <-chan satel.Event {
|
||||
returnChan := make(chan satel.Event)
|
||||
|
||||
go func() {
|
||||
for e := range ev {
|
||||
for _, allowedType := range allowedTypes {
|
||||
if allowedType == e.Type {
|
||||
returnChan <- e
|
||||
continue
|
||||
if len(allowedTypes) == 0 {
|
||||
// no allowed types == all types are allowed
|
||||
go func() {
|
||||
for e := range ev {
|
||||
returnChan <- e
|
||||
}
|
||||
close(returnChan)
|
||||
}()
|
||||
} else {
|
||||
go func() {
|
||||
for e := range ev {
|
||||
for _, allowedType := range allowedTypes {
|
||||
if allowedType == e.Type {
|
||||
returnChan <- e
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(returnChan)
|
||||
}()
|
||||
close(returnChan)
|
||||
}()
|
||||
}
|
||||
|
||||
return returnChan
|
||||
}
|
||||
|
|
|
@ -39,6 +39,32 @@ func TestSatelEventTypeFiltering(t *testing.T) {
|
|||
assert.Contains(t, receivedEvents, satel.Event{Type: satel.PartitionFireAlarm, Index: 4, Value: true})
|
||||
}
|
||||
|
||||
func TestSatelEventTypeFiltering_NoAllowedEventTypesMeansAllAreAllowed(t *testing.T) {
|
||||
testEvents := make(chan satel.Event)
|
||||
receivedEvents := make([]satel.Event, 0)
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
go func() {
|
||||
wg.Add(1)
|
||||
for e := range FilterByType(testEvents, []satel.ChangeType{}) {
|
||||
receivedEvents = append(receivedEvents, e)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
for index, ct := range SUPPORTED_CHANGE_TYPES {
|
||||
testEvents <- satel.Event{Type: ct, Index: index, Value: true}
|
||||
}
|
||||
|
||||
close(testEvents)
|
||||
wg.Wait()
|
||||
|
||||
assert.Len(t, receivedEvents, len(SUPPORTED_CHANGE_TYPES))
|
||||
for index, ct := range SUPPORTED_CHANGE_TYPES {
|
||||
assert.Contains(t, receivedEvents, satel.Event{Type: ct, Index: index, Value: true})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSatelLastSeenFiltering(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "TestSatelLastSeenFiltering")
|
||||
assert.NoError(t, err)
|
||||
|
|
20
main.go
20
main.go
|
@ -68,10 +68,11 @@ func (self RealSleeper) Sleep(ch chan<- interface{}) {
|
|||
}()
|
||||
}
|
||||
|
||||
func getCmdLineParams(logger *log.Logger) (string, []int64) {
|
||||
func getCmdLineParams(logger *log.Logger) (string, []int64, []satel.ChangeType) {
|
||||
satelApiAddr := flag.String("satel-addr", "", "Address that should be used to connect to the SATEL device")
|
||||
satelApiPort := flag.String("satel-port", "7094", "Port that should be used to connect to the SATEL device")
|
||||
chatIdRaw := flag.String("tg-chat-id", "", "Telegram Chat ID where to send updates. Use \",\" to specify multiple IDs.")
|
||||
allowedTypesRaw := flag.String("allowed-types", "", "Satel change types that are allowed. All other types will be discarded. By default all are allowed. Use \",\" to specify multiple types.")
|
||||
flag.Parse()
|
||||
|
||||
if len(*satelApiAddr) == 0 || len(*satelApiPort) == 0 || len(*chatIdRaw) == 0 {
|
||||
|
@ -86,9 +87,18 @@ func getCmdLineParams(logger *log.Logger) (string, []int64) {
|
|||
}
|
||||
chatIds = append(chatIds, chatId)
|
||||
}
|
||||
allowedTypesStrings := strings.Split(*allowedTypesRaw, ",")
|
||||
var allowedTypes []satel.ChangeType
|
||||
for _, allowedTypeStr := range allowedTypesStrings {
|
||||
allowedType, err := StringToSatelChangeType(allowedTypeStr)
|
||||
if err != nil {
|
||||
logger.Fatalf("Error trying to understand an allowed type: %s.", err)
|
||||
}
|
||||
allowedTypes = append(allowedTypes, allowedType)
|
||||
}
|
||||
|
||||
satelAddr := fmt.Sprintf("%s:%s", *satelApiAddr, *satelApiPort)
|
||||
return satelAddr, chatIds
|
||||
return satelAddr, chatIds, allowedTypes
|
||||
}
|
||||
|
||||
func makeSatel(satelAddr string) *satel.Satel {
|
||||
|
@ -107,7 +117,7 @@ func main() {
|
|||
logger = log.New(os.Stderr, "Main", log.Lmicroseconds)
|
||||
)
|
||||
|
||||
satelAddr, chatIds := getCmdLineParams(logger)
|
||||
satelAddr, chatIds, allowedTypes := getCmdLineParams(logger)
|
||||
|
||||
s := makeSatel(satelAddr)
|
||||
logger.Printf("Connected to Satel: %s", satelAddr)
|
||||
|
@ -125,7 +135,9 @@ func main() {
|
|||
tgSenderWorker(tgEvents, &wg, sleeper, log.New(os.Stderr, "TgSender", log.Lmicroseconds)),
|
||||
tgSender, &wg, log.New(os.Stderr, "SendToTg", log.Lmicroseconds)))
|
||||
|
||||
for e := range FilterByLastSeen(s.Events, "hs_wro_last_seen.bin", log.New(os.Stderr, "FilterByLastSeen", log.Lmicroseconds)) {
|
||||
for e := range FilterByType(
|
||||
FilterByLastSeen(s.Events, "hs_wro_last_seen.bin", log.New(os.Stderr, "FilterByLastSeen", log.Lmicroseconds)),
|
||||
allowedTypes) {
|
||||
logger.Print("Received change from SATEL: ", e)
|
||||
for _, chatId := range chatIds {
|
||||
sendTgMessage(tgEvents, SatelMsgContent{e}, chatId)
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/probakowski/go-satel"
|
||||
)
|
||||
|
||||
var SUPPORTED_CHANGE_TYPES = [...]satel.ChangeType{
|
||||
satel.ZoneViolation,
|
||||
satel.ZoneTamper,
|
||||
satel.ZoneAlarm,
|
||||
satel.ZoneTamperAlarm,
|
||||
satel.ZoneAlarmMemory,
|
||||
satel.ZoneTamperAlarmMemory,
|
||||
satel.ZoneBypass,
|
||||
satel.ZoneNoViolationTrouble,
|
||||
satel.ZoneLongViolationTrouble,
|
||||
satel.ArmedPartitionSuppressed,
|
||||
satel.ArmedPartition,
|
||||
satel.PartitionArmedInMode2,
|
||||
satel.PartitionArmedInMode3,
|
||||
satel.PartitionWith1stCodeEntered,
|
||||
satel.PartitionEntryTime,
|
||||
satel.PartitionExitTimeOver10s,
|
||||
satel.PartitionExitTimeUnder10s,
|
||||
satel.PartitionTemporaryBlocked,
|
||||
satel.PartitionBlockedForGuardRound,
|
||||
satel.PartitionAlarm,
|
||||
satel.PartitionFireAlarm,
|
||||
satel.PartitionAlarmMemory,
|
||||
satel.PartitionFireAlarmMemory,
|
||||
satel.Output,
|
||||
satel.DoorOpened,
|
||||
satel.DoorOpenedLong,
|
||||
satel.StatusBit,
|
||||
satel.TroublePart1,
|
||||
satel.TroublePart2,
|
||||
satel.TroublePart3,
|
||||
satel.TroublePart4,
|
||||
satel.TroublePart5,
|
||||
satel.TroubleMemoryPart1,
|
||||
satel.TroubleMemoryPart2,
|
||||
satel.TroubleMemoryPart3,
|
||||
satel.TroubleMemoryPart4,
|
||||
satel.TroubleMemoryPart5,
|
||||
satel.PartitionWithViolatedZones,
|
||||
satel.ZoneIsolate,
|
||||
}
|
||||
|
||||
var SATEL_STRING_TO_CHANGE_TYPE = map[string]satel.ChangeType{
|
||||
"zone-violation": satel.ZoneViolation,
|
||||
"zone-tamper": satel.ZoneTamper,
|
||||
"zone-alarm": satel.ZoneAlarm,
|
||||
"zone-tamper-alarm": satel.ZoneTamperAlarm,
|
||||
"zone-alarm-memory": satel.ZoneAlarmMemory,
|
||||
"zone-tamper-alarm-memory": satel.ZoneTamperAlarmMemory,
|
||||
"zone-bypass": satel.ZoneBypass,
|
||||
"zone-no-violation-trouble": satel.ZoneNoViolationTrouble,
|
||||
"zone-long-violation-trouble": satel.ZoneLongViolationTrouble,
|
||||
"armed-partition-suppressed": satel.ArmedPartitionSuppressed,
|
||||
"armed-partition": satel.ArmedPartition,
|
||||
"partition-armed-mode-2": satel.PartitionArmedInMode2,
|
||||
"partition-armed-mode-3": satel.PartitionArmedInMode3,
|
||||
"partition-with-1st-code-entered": satel.PartitionWith1stCodeEntered,
|
||||
"partition-entry-time": satel.PartitionEntryTime,
|
||||
"partition-exit-time-over-10s": satel.PartitionExitTimeOver10s,
|
||||
"partition-exit-time-under-10s": satel.PartitionExitTimeUnder10s,
|
||||
"partition-temporary-blocked": satel.PartitionTemporaryBlocked,
|
||||
"partition-blocked-guard-round": satel.PartitionBlockedForGuardRound,
|
||||
"partition-alarm": satel.PartitionAlarm,
|
||||
"partition-fire-alarm": satel.PartitionFireAlarm,
|
||||
"partition-alarm-memory": satel.PartitionAlarmMemory,
|
||||
"partition-fire-alarm-memory": satel.PartitionFireAlarmMemory,
|
||||
"output": satel.Output,
|
||||
"doors-opened": satel.DoorOpened,
|
||||
"doors-opened-long": satel.DoorOpenedLong,
|
||||
"status-bit": satel.StatusBit,
|
||||
"trouble-part-1": satel.TroublePart1,
|
||||
"trouble-part-2": satel.TroublePart2,
|
||||
"trouble-part-3": satel.TroublePart3,
|
||||
"trouble-part-4": satel.TroublePart4,
|
||||
"trouble-part-5": satel.TroublePart5,
|
||||
"trouble-memory-part-1": satel.TroubleMemoryPart1,
|
||||
"trouble-memory-part-2": satel.TroubleMemoryPart2,
|
||||
"trouble-memory-part-3": satel.TroubleMemoryPart3,
|
||||
"trouble-memory-part-4": satel.TroubleMemoryPart4,
|
||||
"trouble-memory-part-5": satel.TroubleMemoryPart5,
|
||||
"partition-with-violated-zones": satel.PartitionWithViolatedZones,
|
||||
"zone-isolate": satel.ZoneIsolate,
|
||||
}
|
||||
|
||||
func StringToSatelChangeType(s string) (satel.ChangeType, error) {
|
||||
ct, ok := SATEL_STRING_TO_CHANGE_TYPE[s]
|
||||
if !ok {
|
||||
return 0, errors.New(fmt.Sprint("Unknown change type: ", s))
|
||||
}
|
||||
return ct, nil
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStringToSatelChangeType(t *testing.T) {
|
||||
for _, ct := range SUPPORTED_CHANGE_TYPES {
|
||||
str := ct.String()
|
||||
new_ct, err := StringToSatelChangeType(str)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ct, new_ct)
|
||||
assert.Equal(t, new_ct.String(), str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringToSatelChangeType_UnknownStringPanics(t *testing.T) {
|
||||
_, err := StringToSatelChangeType("smród")
|
||||
assert.Error(t, err, "")
|
||||
}
|
Loading…
Reference in New Issue