/
mqttcommands.go
125 lines (97 loc) · 2.3 KB
/
mqttcommands.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Package mqttservices provides an MQTT broker, topic subscription and publishing methods
package mqttservices
import (
"fmt"
"log"
"net"
"strconv"
"strings"
proto "github.com/huin/mqtt"
"github.com/jeffallen/mqtt"
)
//Store client connection details
var ccPub *mqtt.ClientConn
var ccSub *mqtt.ClientConn
//MqttClient Subscripton struct
type MqttClient struct {
Port string
}
//String returns details of the MqttClient
func (c *MqttClient) String() string {
return fmt.Sprintf("MqttClient: IP %s", c.Port)
}
//NewClient declares a new broker
func NewClient(port string) *MqttClient {
m := &MqttClient{Port: port}
log.Println(m)
return m
}
//Subscribe to MQTT Topic, takes topic as a string
func (c *MqttClient) Subscribe(tl []proto.TopicQos) chan *proto.Publish {
if ccSub == nil {
con, err := net.Dial("tcp", c.Port)
gotError(err)
ccSub = mqtt.NewClientConn(con)
err = ccSub.Connect("", "")
gotError(err)
}
ccSub.Subscribe(tl)
return ccSub.Incoming
}
//Publish MQTT message, takes topic as a string, data as a byte array and retain flag as bool
func (c *MqttClient) Publish(topic string, data string, retain bool) {
if ccPub == nil {
con, err := net.Dial("tcp", c.Port)
gotError(err)
ccPub = mqtt.NewClientConn(con)
err = ccPub.Connect("", "")
gotError(err)
}
ccPub.Publish(&proto.Publish{
Header: proto.Header{
Retain: retain,
},
TopicName: topic,
Payload: proto.BytesPayload(data),
})
}
//PublishMap a Map data entry takes a channel
func (c *MqttClient) PublishMap(chIn chan map[string]interface{}) {
for ch := range chIn {
for k := range ch {
topic := generateTopic(ch["location"].(string))
data := ""
if k != "nodeid" {
if k != "location" {
switch value := ch[k].(type) {
case string:
data = value
case int:
data = strconv.Itoa(value)
case bool:
data = btos(value)
case float64:
data = strconv.FormatFloat(value, 'f', 2, 64)
}
c.Publish(topic+k, data, false)
}
}
}
}
}
//Generate location string
func generateTopic(s string) string {
l := strings.Split(strings.ToLower(s), " ")
loc := "home/"
for _, v := range l {
loc = loc + v + "/"
}
return loc
}
//Quick func to turn a bool to a string representation
func btos(b bool) string {
if b {
return "true"
}
return "false"
}