2024-02-19 18:52:40 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"html/template"
|
2024-03-04 20:11:34 +00:00
|
|
|
"log"
|
2024-02-19 18:52:40 +00:00
|
|
|
"strings"
|
|
|
|
|
2024-03-04 20:11:34 +00:00
|
|
|
"git.sr.ht/~michalr/go-satel"
|
2024-02-19 18:52:40 +00:00
|
|
|
)
|
|
|
|
|
2024-03-06 17:45:12 +00:00
|
|
|
const (
|
|
|
|
ArmedPartition_Armed = true
|
|
|
|
ArmedPartition_Unrmed = false
|
2024-03-06 18:39:43 +00:00
|
|
|
|
|
|
|
PartitionAlarm_Alarm = false
|
|
|
|
PartitionAlarm_AlarmCancelled = true
|
2024-03-06 17:45:12 +00:00
|
|
|
)
|
|
|
|
|
2024-03-04 20:11:34 +00:00
|
|
|
type SatelNameGetter interface {
|
|
|
|
GetName(devType satel.DeviceType, index byte) (*satel.NameEvent, error)
|
|
|
|
}
|
|
|
|
|
2024-02-19 18:52:40 +00:00
|
|
|
type MsgContent struct {
|
2024-03-05 21:30:48 +00:00
|
|
|
SatelEvent satel.BasicEventElement
|
2024-02-19 18:52:40 +00:00
|
|
|
}
|
|
|
|
|
2024-03-04 20:11:34 +00:00
|
|
|
type SatelMsgContent struct {
|
2024-03-05 21:30:48 +00:00
|
|
|
SatelEvent satel.BasicEventElement
|
2024-03-04 20:11:34 +00:00
|
|
|
s SatelNameGetter
|
|
|
|
logger *log.Logger
|
|
|
|
}
|
|
|
|
|
2024-02-19 18:52:40 +00:00
|
|
|
type GenericMessage struct {
|
|
|
|
ChatIds ChatId
|
2024-03-05 21:30:48 +00:00
|
|
|
Messages []satel.BasicEventElement
|
2024-02-19 18:52:40 +00:00
|
|
|
}
|
|
|
|
|
2024-03-04 20:11:34 +00:00
|
|
|
type SatelMessage struct {
|
|
|
|
ChatIds ChatId
|
|
|
|
Messages []SatelMsgContent
|
|
|
|
}
|
|
|
|
|
2024-03-05 21:30:48 +00:00
|
|
|
func getSatelMessageContent(messages []satel.BasicEventElement, s SatelNameGetter, logger *log.Logger) []SatelMsgContent {
|
2024-03-04 20:11:34 +00:00
|
|
|
retval := make([]SatelMsgContent, len(messages))
|
|
|
|
for i, v := range messages {
|
2024-03-05 21:30:48 +00:00
|
|
|
retval[i] = SatelMsgContent{v, s, logger}
|
2024-03-04 20:11:34 +00:00
|
|
|
}
|
|
|
|
return retval
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self SatelMsgContent) GetName() string {
|
|
|
|
if self.SatelEvent.Type == satel.ArmedPartition {
|
|
|
|
// Satel has 1-based indexes of partitions, go-satel has 0-based
|
|
|
|
name, err := self.s.GetName(satel.DeviceType_Partition, byte(self.SatelEvent.Index+1))
|
|
|
|
if err != nil {
|
|
|
|
self.logger.Print("Could not get partition name: ", err)
|
|
|
|
return fmt.Sprint("Partition#", self.SatelEvent.Index)
|
|
|
|
}
|
|
|
|
return name.DevName
|
|
|
|
} else {
|
|
|
|
return self.IndexDesc()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self GenericMessage) Format(template *template.Template, s SatelNameGetter, logger *log.Logger) string {
|
2024-02-19 18:52:40 +00:00
|
|
|
b := strings.Builder{}
|
2024-03-04 20:11:34 +00:00
|
|
|
template.Execute(&b, SatelMessage{
|
|
|
|
self.ChatIds,
|
|
|
|
getSatelMessageContent(self.Messages, s, logger),
|
|
|
|
})
|
2024-02-19 18:52:40 +00:00
|
|
|
return b.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func getEmojiWhenTrueIsGood(v bool) string {
|
|
|
|
if v {
|
|
|
|
return "✅"
|
|
|
|
} else {
|
|
|
|
return "🔴"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func getEmojiWhenTrueIsBad(v bool) string {
|
|
|
|
if v {
|
|
|
|
return "🔴"
|
|
|
|
} else {
|
|
|
|
return "✅"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 21:42:03 +00:00
|
|
|
func getArmedPartitionStatus(v bool) string {
|
2024-03-06 17:45:12 +00:00
|
|
|
if v == ArmedPartition_Armed {
|
2024-03-05 21:42:03 +00:00
|
|
|
return "✅ - ARMED"
|
|
|
|
} else {
|
|
|
|
return "🔴 - DISARMED"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 18:39:43 +00:00
|
|
|
func getPartitionAlarmStatus(v bool) string {
|
|
|
|
if v == PartitionAlarm_Alarm {
|
|
|
|
return "⚠️⚠️ ALARM! ⚠️⚠️"
|
|
|
|
} else {
|
|
|
|
return "Alarm cancelled"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-04 20:11:34 +00:00
|
|
|
func (self SatelMsgContent) FormatEvent() string {
|
2024-02-19 18:52:40 +00:00
|
|
|
switch self.SatelEvent.Type {
|
|
|
|
case satel.ZoneViolation:
|
|
|
|
return fmt.Sprintf("%s: %s", self.SatelEvent.Type.String(), getEmojiWhenTrueIsBad(self.SatelEvent.Value))
|
|
|
|
case satel.ZoneTamper:
|
|
|
|
return fmt.Sprintf("%s: %s", self.SatelEvent.Type.String(), getEmojiWhenTrueIsBad(self.SatelEvent.Value))
|
|
|
|
case satel.ZoneAlarm:
|
|
|
|
return fmt.Sprintf("%s: %s", self.SatelEvent.Type.String(), getEmojiWhenTrueIsBad(self.SatelEvent.Value))
|
|
|
|
case satel.ZoneTamperAlarm:
|
|
|
|
return fmt.Sprintf("%s: %s", self.SatelEvent.Type.String(), getEmojiWhenTrueIsBad(self.SatelEvent.Value))
|
|
|
|
case satel.ZoneAlarmMemory:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.ZoneTamperAlarmMemory:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.ZoneBypass:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.ZoneNoViolationTrouble:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.ZoneLongViolationTrouble:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.ArmedPartitionSuppressed:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.ArmedPartition:
|
2024-03-05 21:42:03 +00:00
|
|
|
return getArmedPartitionStatus(self.SatelEvent.Value)
|
2024-02-19 18:52:40 +00:00
|
|
|
case satel.PartitionArmedInMode2:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionArmedInMode3:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionWith1stCodeEntered:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionEntryTime:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionExitTimeOver10s:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionExitTimeUnder10s:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionTemporaryBlocked:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionBlockedForGuardRound:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionAlarm:
|
2024-03-06 18:39:43 +00:00
|
|
|
return getPartitionAlarmStatus(self.SatelEvent.Value)
|
2024-02-19 18:52:40 +00:00
|
|
|
case satel.PartitionFireAlarm:
|
|
|
|
return fmt.Sprintf("%s: %s", self.SatelEvent.Type.String(), getEmojiWhenTrueIsBad(self.SatelEvent.Value))
|
|
|
|
case satel.PartitionAlarmMemory:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionFireAlarmMemory:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.Output:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.DoorOpened:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.DoorOpenedLong:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.StatusBit:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroublePart1:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroublePart2:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroublePart3:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroublePart4:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroublePart5:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroubleMemoryPart1:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroubleMemoryPart2:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroubleMemoryPart3:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroubleMemoryPart4:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.TroubleMemoryPart5:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.PartitionWithViolatedZones:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
case satel.ZoneIsolate:
|
|
|
|
return fmt.Sprintf("%s: %t", self.SatelEvent.Type.String(), self.SatelEvent.Value)
|
|
|
|
}
|
|
|
|
panic(fmt.Sprint("Unknown event received: ", self.SatelEvent))
|
|
|
|
}
|
2024-03-03 13:25:34 +00:00
|
|
|
|
2024-03-04 20:11:34 +00:00
|
|
|
func (self SatelMsgContent) IndexDesc() string {
|
2024-03-03 13:25:34 +00:00
|
|
|
switch self.SatelEvent.Type {
|
|
|
|
case satel.ZoneViolation:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneTamper:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneAlarm:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneTamperAlarm:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneAlarmMemory:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneTamperAlarmMemory:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneBypass:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneNoViolationTrouble:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneLongViolationTrouble:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
case satel.ArmedPartitionSuppressed:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.ArmedPartition:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionArmedInMode2:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionArmedInMode3:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionWith1stCodeEntered:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionEntryTime:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionExitTimeOver10s:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionExitTimeUnder10s:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionTemporaryBlocked:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionBlockedForGuardRound:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionAlarm:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionFireAlarm:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionAlarmMemory:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.PartitionFireAlarmMemory:
|
|
|
|
return fmt.Sprintf("Partition %d", self.SatelEvent.Index)
|
|
|
|
case satel.ZoneIsolate:
|
|
|
|
return fmt.Sprintf("Zone %d", self.SatelEvent.Index)
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("Unknown index: %d", self.SatelEvent.Index)
|
|
|
|
}
|