refactoring

This commit is contained in:
Javier Peletier committed 2020-12-14 20:05:34 +01:00
1 parent 119adb54db
commit bb7dba5e85
4 files changed
+282 -174

No files matched your search

+65 -167
View File
@@ -9,7 +9,9 @@ import (
"log"
"os"
"os/signal"
"regexp"
"strconv"
"strings"
"syscall"
"time"
@@ -17,8 +19,6 @@ import (
"github.com/goburrow/modbus"
)
const NUM_ZONES = 16
func buildReader(handler *modbus.RTUClientHandler, client modbus.Client) watcher.ReadRegister {
return func(slaveID byte, address uint16, quantity uint16) (results []byte, err error) {
handler.SlaveId = slaveID
@@ -27,31 +27,23 @@ func buildReader(handler *modbus.RTUClientHandler, client modbus.Client) watcher
}
}
func getActiveZones(w kn.Watcher) ([]*kn.Zone, error) {
var zones []*kn.Zone
for n := 0; n < NUM_ZONES; n++ {
zone := kn.NewZone(&kn.ZoneConfig{
ZoneNumber: n,
Watcher: w,
})
isPresent, err := zone.IsPresent()
if err != nil {
return nil, err
}
if isPresent {
zones = append(zones, zone)
temp, _ := zone.GetCurrentTemperature()
fmt.Printf("Zone %d is present. Temperature %g ºC\n", zone.ZoneNumber, temp)
}
func generateNodeName(slaveID string, port string) string {
reg, err := regexp.Compile("[^a-zA-Z0-9]+")
if err != nil {
log.Fatal(err)
}
return zones, nil
hostname, _ := os.Hostname()
port = strings.Replace(port, "/dev/", "", -1)
port = reg.ReplaceAllString(port, "")
return strings.ToLower(fmt.Sprintf("%s_%s_%s", hostname, port, slaveID))
}
func main() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
ctrlC := make(chan os.Signal, 1)
signal.Notify(ctrlC, os.Interrupt, syscall.SIGTERM)
hostname, _ := os.Hostname()
@@ -62,15 +54,21 @@ func main() {
username := flag.String("username", "", "A username to authenticate to the MQTT server")
password := flag.String("password", "", "Password to match username")
prefix := flag.String("prefix", "koolnova2mqtt", "MQTT topic root where to publish/read topics")
modbusPort := flag.String("modbusPort", "/dev/ttyUSB0", "Serial port where modbus hardware is connected")
modbusPortBaudRate := flag.Int("modbusRate", 9600, "Modbus port data rate")
modbusDataBits := flag.Int("modbusDataBits", 8, "Modbus port data bits")
modbusPortParity := flag.String("modbusParity", "E", "N - None, E - Even, O - Odd (default E) (The use of no parity requires 2 stop bits.)")
modbusStopBits := flag.Int("modbusStopBits", 1, "Modbus port stop bits")
modbusSlaveList := flag.String("modbusSlaveIDs", "49", "Comma-separated list of modbus slave IDs to manage")
modbusSlaveNames := flag.String("modbusSlaveNames", "", "Comma-separated list of modbus slave names. Defaults to 'slave#'")
flag.Parse()
// Modbus RTU/ASCII
handler := modbus.NewRTUClientHandler("/dev/remserial1")
handler.BaudRate = 9600
handler.DataBits = 8
handler.Parity = "E"
handler.StopBits = 1
handler.SlaveId = 49
handler := modbus.NewRTUClientHandler(*modbusPort)
handler.BaudRate = *modbusPortBaudRate
handler.DataBits = *modbusDataBits
handler.Parity = *modbusPortParity
handler.StopBits = *modbusStopBits
handler.Timeout = 5 * time.Second
err := handler.Connect()
@@ -79,57 +77,46 @@ func main() {
}
defer handler.Close()
client := modbus.NewClient(handler)
modbusClient := modbus.NewClient(handler)
nodeName := "topFloors"
registerReader := buildReader(handler, modbusClient)
getZoneTopic := func(zoneNum int, subtopic string) string {
return fmt.Sprintf("%s/%s/zone%d/%s", *prefix, nodeName, zoneNum, subtopic)
var mqttClient MQTT.Client
publish := func(topic string, qos byte, retained bool, payload string) {
mqttClient.Publish(topic, qos, retained, payload)
}
getSysTopic := func(subtopic string) string {
return fmt.Sprintf("%s/%s/sys/%s", *prefix, nodeName, subtopic)
var snameList []string
slist := strings.Split(*modbusSlaveList, ",")
if *modbusSlaveNames == "" {
for _, slaveIDStr := range slist {
snameList = append(snameList, generateNodeName(slaveIDStr, *modbusPort))
}
} else {
snameList = strings.Split(*modbusSlaveNames, ",")
if len(slist) != len(snameList) {
log.Fatalf("modbusSlaveIDs and modbusSlaveNames lists must have the same length")
}
}
getACTopic := func(ac kn.ACMachine, subtopic string) string {
return getSysTopic(fmt.Sprintf("ac%d/%s", ac, subtopic))
var bridges []*kn.Bridge
for i, slaveIDStr := range slist {
slaveID, err := strconv.Atoi(slaveIDStr)
slaveName := snameList[i]
if err != nil {
log.Fatalf("Error parsing slaveID list")
}
bridge := kn.NewBridge(&kn.Config{
ModuleName: slaveName,
SlaveID: byte(slaveID),
Publish: publish,
TopicPrefix: *prefix,
ReadRegister: registerReader,
})
bridges = append(bridges, bridge)
}
registerReader := buildReader(handler, client)
zw := watcher.New(&watcher.Config{
Address: 1,
Quantity: 64,
RegisterSize: 2,
SlaveID: 49,
Read: registerReader,
})
sysw := watcher.New(&watcher.Config{
Address: kn.REG_AIRFLOW,
Quantity: 18,
RegisterSize: 2,
SlaveID: 49,
Read: registerReader,
})
err = zw.Poll()
if err != nil {
fmt.Println(err)
return
}
err = sysw.Poll()
if err != nil {
fmt.Println(err)
return
}
zones, err := getActiveZones(zw)
sys := kn.NewSys(&kn.SysConfig{
Watcher: sysw,
})
connOpts := MQTT.NewClientOptions().AddBroker(*server).SetClientID(*clientid).SetCleanSession(true)
if *username != "" {
connOpts.SetUsername(*username)
@@ -139,96 +126,13 @@ func main() {
}
tlsConfig := &tls.Config{InsecureSkipVerify: true, ClientAuth: tls.NoClientCert}
connOpts.SetTLSConfig(tlsConfig)
connOpts.OnConnect = func(c MQTT.Client) {
/* if token := c.Subscribe(*topic, byte(*qos), onMessageReceived); token.Wait() && token.Error() != nil {
panic(token.Error())
} */
zw.TriggerCallbacks()
sysw.TriggerCallbacks()
bauds, err := sys.GetBaudRate()
if err != nil {
log.Printf("Error reading configured serial baud rate: %s", err)
}
parity, err := sys.GetParity()
if err != nil {
log.Printf("Error reading configured serial parity: %s", err)
}
slaveID, err := sys.GetSlaveID()
if err != nil {
log.Printf("Error reading configured modbus slave ID: %s", err)
}
c.Publish(getSysTopic("serialBaud"), 0, false, strconv.Itoa(bauds))
c.Publish(getSysTopic("serialParity"), 0, false, parity)
c.Publish(getSysTopic("slaveId"), 0, false, slaveID)
}
mqttClient := MQTT.NewClient(connOpts)
for _, zone := range zones {
zone := zone
zone.OnCurrentTempChange = func(currentTemp float32) {
mqttClient.Publish(getZoneTopic(zone.ZoneNumber, "currentTemp"), 0, false, fmt.Sprintf("%g", currentTemp))
}
zone.OnTargetTempChange = func(targetTemp float32) {
mqttClient.Publish(getZoneTopic(zone.ZoneNumber, "targetTemp"), 0, false, fmt.Sprintf("%g", targetTemp))
}
zone.OnFanModeChange = func(fanMode kn.FanMode) {
mqttClient.Publish(getZoneTopic(zone.ZoneNumber, "fanMode"), 0, false, kn.FanMode2Str(fanMode))
}
zone.OnHvacModeChange = func(hvacMode kn.HvacMode) {
mqttClient.Publish(getZoneTopic(zone.ZoneNumber, "hvacMode"), 0, false, kn.HvacMode2Str(hvacMode))
for _, b := range bridges {
b.Start()
}
}
sys.OnACAirflowChange = func(ac kn.ACMachine) {
airflow, err := sys.GetAirflow(ac)
if err != nil {
log.Printf("Error reading airflow of AC %d: %s", ac, err)
return
}
mqttClient.Publish(getACTopic(ac, "airflow"), 0, false, strconv.Itoa(airflow))
}
sys.OnACTargetTempChange = func(ac kn.ACMachine) {
targetTemp, err := sys.GetMachineTargetTemp(ac)
if err != nil {
log.Printf("Error reading target temp of AC %d: %s", ac, err)
return
}
mqttClient.Publish(getACTopic(ac, "targetTemp"), 0, false, fmt.Sprintf("%g", targetTemp))
}
sys.OnACTargetFanModeChange = func(ac kn.ACMachine) {
targetAirflow, err := sys.GetTargetFanMode(ac)
if err != nil {
log.Printf("Error reading target airflow of AC %d: %s", ac, err)
return
}
mqttClient.Publish(getACTopic(ac, "fanMode"), 0, false, kn.FanMode2Str(targetAirflow))
}
sys.OnEfficiencyChange = func() {
efficiency, err := sys.GetEfficiency()
if err != nil {
log.Printf("Error reading efficiency value: %s", err)
return
}
mqttClient.Publish(getSysTopic("efficiency"), 0, false, strconv.Itoa(efficiency))
}
sys.OnSystemEnabledChange = func() {
enabled, err := sys.GetSystemEnabled()
if err != nil {
log.Printf("Error reading enabled value: %s", err)
return
}
mqttClient.Publish(getSysTopic("enabled"), 0, false, fmt.Sprintf("%t", enabled))
}
sys.OnHvacModeChange = func() {
mode, err := sys.GetSystemHVACMode()
if err != nil {
log.Printf("Error reading hvac mode: %s", err)
return
}
mqttClient.Publish(getSysTopic("hvacMode"), 0, false, kn.HvacMode2Str(mode))
}
mqttClient = MQTT.NewClient(connOpts)
if token := mqttClient.Connect(); token.Wait() && token.Error() != nil {
panic(token.Error())
@@ -240,18 +144,12 @@ func main() {
go func() {
for range ticker.C {
err := zw.Poll()
if err != nil {
log.Printf("Error polling zones over modbus: %s\n", err)
}
err = sysw.Poll()
if err != nil {
log.Printf("Error polling system config over modbus: %s\n", err)
for _, b := range bridges {
b.Tick()
}
}
}()
<-c
<-ctrlC
}