2024-03-23 09:40:20 +00:00
package main
import (
2024-03-24 08:32:03 +00:00
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
2024-03-23 09:40:20 +00:00
"time"
"git.sr.ht/~michalr/go-satel"
2024-03-24 17:39:12 +00:00
"gopkg.in/yaml.v3"
2024-03-23 09:40:20 +00:00
)
2024-03-24 17:39:12 +00:00
const (
ConfigFilePath = "hswro-alarm-bot.yml"
)
type OwnDuration struct {
duration time . Duration
}
type SatelChangeType struct {
changeType satel . ChangeType
}
2024-08-24 09:56:32 +00:00
type MqttConfig struct {
Enabled bool ` yaml:"mqtt-enabled" `
BrokerUri string ` yaml:"mqtt-broker-uri" `
Username string ` yaml:"mqtt-username" `
Password string ` yaml:"mqtt-password" `
}
2024-03-23 09:40:20 +00:00
type AppConfig struct {
2024-03-24 17:39:12 +00:00
SatelAddr string ` yaml:"satel-addr" `
ChatIds [ ] int64 ` yaml:"tg-chat-ids" `
AllowedTypes [ ] SatelChangeType ` yaml:"allowed-types" `
AllowedIndexes [ ] int ` yaml:"allowed-indexes" `
PoolInterval OwnDuration ` yaml:"pool-interval" `
ArmCallbackUrls [ ] string ` yaml:"arm-callback-urls" `
DisarmCallbackUrls [ ] string ` yaml:"disarm-callback-urls" `
AlarmCallbackUrls [ ] string ` yaml:"alarm-callback-urls" `
2024-04-06 10:08:41 +00:00
WriteMemoryProfile bool ` yaml:"write-memory-profile" `
2024-08-24 09:56:32 +00:00
MqttConfiguration MqttConfig ` yaml:"mqtt" `
2024-03-24 17:39:12 +00:00
}
func ( m * SatelChangeType ) UnmarshalYAML ( unmarshal func ( interface { } ) error ) error {
var inputStr string
err := unmarshal ( & inputStr )
if err != nil {
return err
}
ct , err := StringToSatelChangeType ( inputStr )
if err != nil {
return err
}
* m = SatelChangeType { ct }
return nil
}
func ( m * OwnDuration ) UnmarshalYAML ( unmarshal func ( interface { } ) error ) error {
var inputStr string
err := unmarshal ( & inputStr )
if err != nil {
return err
}
duration , err := time . ParseDuration ( inputStr )
if err != nil {
return err
}
* m = OwnDuration { duration }
return nil
}
func ( self SatelChangeType ) GetChangeType ( ) satel . ChangeType { return self . changeType }
func ( self OwnDuration ) GetDuration ( ) time . Duration { return self . duration }
func loadConfigFromFile ( filePath string , logger * log . Logger ) AppConfig {
f , err := os . ReadFile ( filePath )
if err != nil {
logger . Print ( "Error opening config file: " , err , ". Trying to continue without it" )
return AppConfig { }
}
return parseConfigFromFile ( f , logger )
}
func parseConfigFromFile ( contents [ ] byte , logger * log . Logger ) AppConfig {
var config AppConfig
err := yaml . Unmarshal ( contents , & config )
if err != nil {
logger . Print ( "Error while parsing config file: " , err , ". Trying to continue without it" )
return AppConfig { }
}
return config
2024-03-24 08:32:03 +00:00
}
func getCmdLineParams ( config * AppConfig , logger * log . Logger ) {
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." )
allowedIndexesRaw := flag . String ( "allowed-indexes" , "" , "Satel indexes (zones?) that are allowed. All other indexes will be discarded. By default all are allowed. Use \",\" to specify multiple indexes." )
satelPoolInterval := flag . Duration ( "pool-interval" , 5 * time . Second , "How often should the SATEL device be pooled for changes? Default: 5 seconds." )
2024-04-06 10:08:41 +00:00
writeMemoryProfile := flag . Bool ( "write-memory-profile" , false , "Whether application should dump its memory profile every 24 hours. Default: false" )
2024-03-24 08:32:03 +00:00
flag . Parse ( )
if len ( * satelApiAddr ) == 0 || len ( * satelApiPort ) == 0 || len ( * chatIdRaw ) == 0 {
logger . Fatal ( "Use --satel-addr=ADDR, --satel-port=PORT and --tg-chat-id=CHAT_ID command line flags to continue." )
}
chatIdsStrings := strings . Split ( * chatIdRaw , "," )
var chatIds [ ] int64
for _ , chatIdStr := range chatIdsStrings {
chatId , err := strconv . ParseInt ( chatIdStr , 10 , 64 )
if err != nil {
logger . Fatalf ( "Tried to use a non-int value for one of tg_chatIds: %s. That's bad." , chatIdStr )
}
chatIds = append ( chatIds , chatId )
}
allowedTypesStrings := strings . Split ( * allowedTypesRaw , "," )
2024-03-24 17:39:12 +00:00
var allowedTypes [ ] SatelChangeType
2024-03-24 08:32:03 +00:00
for _ , allowedTypeStr := range allowedTypesStrings {
if len ( allowedTypeStr ) == 0 {
continue
}
allowedType , err := StringToSatelChangeType ( allowedTypeStr )
if err != nil {
logger . Fatalf ( "Error trying to understand an allowed type: %s." , err )
}
2024-03-24 17:39:12 +00:00
allowedTypes = append ( allowedTypes , SatelChangeType { allowedType } )
2024-03-24 08:32:03 +00:00
}
allowedIndexesStrings := strings . Split ( * allowedIndexesRaw , "," )
var allowedIndexes [ ] int
for _ , allowedIndexStr := range allowedIndexesStrings {
if len ( allowedIndexStr ) == 0 {
continue
}
allowedIndex , err := strconv . ParseInt ( allowedIndexStr , 10 , 0 )
if err != nil {
logger . Fatalf ( "Tried to use a non-int value for one of allowed indexes: %s. That's bad." , allowedIndexStr )
}
allowedIndexes = append ( allowedIndexes , int ( allowedIndex ) )
}
2024-04-06 10:08:41 +00:00
if writeMemoryProfile != nil {
config . WriteMemoryProfile = * writeMemoryProfile
}
2024-03-24 08:32:03 +00:00
satelAddr := fmt . Sprintf ( "%s:%s" , * satelApiAddr , * satelApiPort )
2024-03-24 15:54:33 +00:00
config . SatelAddr = satelAddr
config . ChatIds = chatIds
config . AllowedTypes = allowedTypes
config . AllowedIndexes = allowedIndexes
2024-03-24 17:39:12 +00:00
config . PoolInterval = OwnDuration { * satelPoolInterval }
2024-03-24 08:32:03 +00:00
}
func MakeConfig ( logger * log . Logger ) AppConfig {
2024-03-24 17:39:12 +00:00
config := loadConfigFromFile ( ConfigFilePath , logger )
2024-03-24 15:54:33 +00:00
config . ArmCallbackUrls = [ ] string { }
config . DisarmCallbackUrls = [ ] string { }
config . AlarmCallbackUrls = [ ] string { }
2024-04-06 10:08:41 +00:00
config . WriteMemoryProfile = false
2024-03-24 08:32:03 +00:00
if len ( os . Getenv ( "NOTIFY_URL_ARM" ) ) != 0 {
2024-03-24 15:54:33 +00:00
config . ArmCallbackUrls = append ( config . ArmCallbackUrls , os . Getenv ( "NOTIFY_URL_ARM" ) )
2024-03-24 08:32:03 +00:00
}
if len ( os . Getenv ( "NOTIFY_URL_DISARM" ) ) != 0 {
2024-03-24 15:54:33 +00:00
config . DisarmCallbackUrls = append ( config . DisarmCallbackUrls , os . Getenv ( "NOTIFY_URL_DISARM" ) )
2024-03-24 08:32:03 +00:00
}
if len ( os . Getenv ( "ALARM_URL_ARM" ) ) != 0 {
2024-03-24 15:54:33 +00:00
config . AlarmCallbackUrls = append ( config . AlarmCallbackUrls , os . Getenv ( "ALARM_URL_ARM" ) )
2024-03-24 08:32:03 +00:00
}
getCmdLineParams ( & config , logger )
return config
2024-03-23 09:40:20 +00:00
}