dhcp4d: optionally publish DHCP leases to MQTT
Enable using: mkdir -p /perm/dhcp4d echo 'tcp://10.0.0.54:1883' > /perm/dhcp4d/mqtt-broker.txt
This commit is contained in:
parent
e5ea79aef8
commit
04f2be01d9
@ -234,6 +234,8 @@ type srv struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newSrv(permDir string) (*srv, error) {
|
func newSrv(permDir string) (*srv, error) {
|
||||||
|
mayqtt := MQTT()
|
||||||
|
|
||||||
http.Handle("/metrics", promhttp.Handler())
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
if err := updateListeners(); err != nil {
|
if err := updateListeners(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -399,6 +401,30 @@ func newSrv(permDir string) (*srv, error) {
|
|||||||
if err := notify.Process("/user/dnsd", syscall.SIGUSR1); err != nil {
|
if err := notify.Process("/user/dnsd", syscall.SIGUSR1); err != nil {
|
||||||
log.Printf("notifying dnsd: %v", err)
|
log.Printf("notifying dnsd: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Publish the DHCP lease as JSON to MQTT, if configured:
|
||||||
|
leaseVal := struct {
|
||||||
|
Addr string `json:"addr"`
|
||||||
|
HardwareAddr string `json:"hardware_addr"`
|
||||||
|
Expiration time.Time `json:"expiration"`
|
||||||
|
}{
|
||||||
|
Addr: latest.Addr.String(),
|
||||||
|
HardwareAddr: latest.HardwareAddr,
|
||||||
|
Expiration: latest.Expiry.In(time.UTC),
|
||||||
|
}
|
||||||
|
leaseJSON, err := json.Marshal(leaseVal)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
identifier := latest.Hostname
|
||||||
|
if identifier == "" {
|
||||||
|
identifier = latest.HardwareAddr
|
||||||
|
}
|
||||||
|
mayqtt <- PublishRequest{
|
||||||
|
Topic: "router7/dhcp4d/lease/" + identifier,
|
||||||
|
Retained: true,
|
||||||
|
Payload: leaseJSON,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
conn, err := conn.NewUDP4BoundListener(*iface, ":67")
|
conn, err := conn.NewUDP4BoundListener(*iface, ":67")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
53
cmd/dhcp4d/mayqtt.go
Normal file
53
cmd/dhcp4d/mayqtt.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PublishRequest struct {
|
||||||
|
Topic string
|
||||||
|
Qos byte
|
||||||
|
Retained bool
|
||||||
|
Payload interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func publisherLoop(requests <-chan PublishRequest) error {
|
||||||
|
const configFn = "/perm/dhcp4d/mqtt-broker.txt"
|
||||||
|
b, err := ioutil.ReadFile(configFn)
|
||||||
|
if err != nil {
|
||||||
|
// discard requests:
|
||||||
|
for range requests {
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// e.g. tcp://10.0.0.54:1883, which is a static DHCP lease for the dr.lan
|
||||||
|
// Raspberry Pi, which is running an MQTT broker in my network.
|
||||||
|
broker := strings.TrimSpace(string(b))
|
||||||
|
log.Printf("Connecting to MQTT broker %q (configured in %s)", broker, configFn)
|
||||||
|
opts := mqtt.NewClientOptions().AddBroker(broker)
|
||||||
|
opts.SetClientID("dhcp4d")
|
||||||
|
mqttClient := mqtt.NewClient(opts)
|
||||||
|
if token := mqttClient.Connect(); token.Wait() && token.Error() != nil {
|
||||||
|
return fmt.Errorf("MQTT connection failed: %v", token.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for r := range requests {
|
||||||
|
// discard Token, MQTT publishing is best-effort
|
||||||
|
_ = mqttClient.Publish(r.Topic, r.Qos, r.Retained, r.Payload)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MQTT() chan<- PublishRequest {
|
||||||
|
result := make(chan PublishRequest)
|
||||||
|
go func() {
|
||||||
|
if err := publisherLoop(result); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return result
|
||||||
|
}
|
1
go.mod
1
go.mod
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/digineo/go-ping v1.0.0
|
github.com/digineo/go-ping v1.0.0
|
||||||
github.com/gokrazy/breakglass v0.0.0-20200527163858-efff2172eebe // indirect
|
github.com/gokrazy/breakglass v0.0.0-20200527163858-efff2172eebe // indirect
|
||||||
github.com/gokrazy/gdns v0.0.0-20200218203540-6b3b6244ea39 // indirect
|
github.com/gokrazy/gdns v0.0.0-20200218203540-6b3b6244ea39 // indirect
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.2.0
|
||||||
github.com/gokrazy/gokrazy v0.0.0-20201006151115-caded4667633
|
github.com/gokrazy/gokrazy v0.0.0-20201006151115-caded4667633
|
||||||
github.com/gokrazy/internal v0.0.0-20200713084155-ab6fc6e02a03 // indirect
|
github.com/gokrazy/internal v0.0.0-20200713084155-ab6fc6e02a03 // indirect
|
||||||
github.com/gokrazy/timestamps v0.0.0-20200713073712-54fdc319126e // indirect
|
github.com/gokrazy/timestamps v0.0.0-20200713073712-54fdc319126e // indirect
|
||||||
|
1
go.sum
1
go.sum
@ -70,6 +70,7 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
|||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0=
|
||||||
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
|
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
|
||||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user