mirror of
https://github.com/Luzifer/culmqtt.git
synced 2024-12-22 18:51:22 +00:00
Initial version
This commit is contained in:
commit
3df2537c8d
4 changed files with 155 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
culmqtt
|
46
fs20.go
Normal file
46
fs20.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processFS20Message(housecode, device, command string) error {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"housecode": housecode,
|
||||||
|
"device": device,
|
||||||
|
"command": command,
|
||||||
|
}).Info("FS20 status received")
|
||||||
|
|
||||||
|
return publishFS20ToMQTT(housecode, device, command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishFS20ToCUL(client mqtt.Client, msg mqtt.Message) {
|
||||||
|
addr := strings.Split(msg.Topic(), "/")[1]
|
||||||
|
cmd := string(msg.Payload())
|
||||||
|
|
||||||
|
logger := log.WithFields(log.Fields{
|
||||||
|
"address": addr,
|
||||||
|
"command": cmd,
|
||||||
|
})
|
||||||
|
|
||||||
|
if _, err := fmt.Fprintf(port, "F%s%s\n", addr, cmd); err != nil {
|
||||||
|
logger.WithError(err).Error("Unable to send message through CUL")
|
||||||
|
}
|
||||||
|
logger.Info("Message sent")
|
||||||
|
}
|
||||||
|
|
||||||
|
func publishFS20ToMQTT(housecode, device, command string) error {
|
||||||
|
tok := brokerClient.Publish(
|
||||||
|
strings.Join([]string{"culmqtt", fmt.Sprintf("%s%s", housecode, device), "state"}, "/"),
|
||||||
|
0x01, // QOS Level 1: At least once
|
||||||
|
true,
|
||||||
|
command,
|
||||||
|
)
|
||||||
|
|
||||||
|
tok.Wait()
|
||||||
|
return tok.Error()
|
||||||
|
}
|
91
main.go
Normal file
91
main.go
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/Luzifer/rconfig"
|
||||||
|
"github.com/jacobsa/go-serial/serial"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cfg = struct {
|
||||||
|
CULDevice string `flag:"cul-device" default:"/dev/ttyACM0" env:"CUL_DEVICE" description:"TTY of the CUL to connect to"`
|
||||||
|
LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"`
|
||||||
|
MQTTHost string `flag:"mqtt-host" default:"tcp://127.0.0.1:1883" env:"MQTT_HOST" description:"Connection URI for the broker"`
|
||||||
|
MQTTUser string `flag:"mqtt-user" default:"" env:"MQTT_USER" description:"Username for broker connection"`
|
||||||
|
MQTTPass string `flag:"mqtt-pass" default:"" env:"MQTT_PASS" description:"Password for broker connection"`
|
||||||
|
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
port io.ReadWriteCloser
|
||||||
|
|
||||||
|
version = "dev"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if err := rconfig.ParseAndValidate(&cfg); err != nil {
|
||||||
|
log.Fatalf("Unable to parse commandline options: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.VersionAndExit {
|
||||||
|
fmt.Printf("culmqtt %s\n", version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if l, err := log.ParseLevel(cfg.LogLevel); err != nil {
|
||||||
|
log.WithError(err).Fatal("Unable to parse log level")
|
||||||
|
} else {
|
||||||
|
log.SetLevel(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
options := serial.OpenOptions{
|
||||||
|
PortName: cfg.CULDevice,
|
||||||
|
BaudRate: 19200,
|
||||||
|
DataBits: 8,
|
||||||
|
StopBits: 1,
|
||||||
|
MinimumReadSize: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the port.
|
||||||
|
var err error
|
||||||
|
if port, err = serial.Open(options); err != nil {
|
||||||
|
log.Fatalf("serial.Open: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure to close it later.
|
||||||
|
defer port.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
scanner := bufio.NewScanner(port)
|
||||||
|
for scanner.Scan() {
|
||||||
|
if err := processMessage(scanner.Text()); err != nil {
|
||||||
|
log.WithError(err).Fatal("Unable to process message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processMessage(message string) error {
|
||||||
|
logger := log.WithField("message", message)
|
||||||
|
|
||||||
|
switch message[0] {
|
||||||
|
case 'F':
|
||||||
|
return processFS20Message(
|
||||||
|
message[1:5], // House code: 4 hex digits
|
||||||
|
message[5:7], // Device code: 2 hex digits
|
||||||
|
message[7:9], // Command: 2 hex digits
|
||||||
|
)
|
||||||
|
case 'V':
|
||||||
|
// Version information, discard
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
logger.Error("Unknown message specifier")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
17
mqtt.go
Normal file
17
mqtt.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
|
||||||
|
var brokerClient mqtt.Client
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
opts := mqtt.NewClientOptions().AddBroker(cfg.MQTTHost)
|
||||||
|
if cfg.MQTTUser != "" || cfg.MQTTPass != "" {
|
||||||
|
opts.SetUsername(cfg.MQTTUser).SetPassword(cfg.MQTTPass)
|
||||||
|
}
|
||||||
|
|
||||||
|
brokerClient = mqtt.NewClient(opts)
|
||||||
|
|
||||||
|
brokerClient.Connect().Wait()
|
||||||
|
brokerClient.Subscribe("culmqtt/+/send", 0x01, publishFS20ToCUL)
|
||||||
|
}
|
Loading…
Reference in a new issue