Browse Source

show current state of lights.

Thomas Buck 1 year ago
parent
commit
a97051aad9
3 changed files with 117 additions and 7 deletions
  1. 46
    0
      Makefile
  2. 4
    0
      README.md
  3. 67
    7
      lights-telegram.go

+ 46
- 0
Makefile View File

@@ -0,0 +1,46 @@
1
+# ----------------------------------------------------------------------------
2
+# "THE BEER-WARE LICENSE" (Revision 42):
3
+# <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
4
+# you can do whatever you want with this stuff. If we meet some day, and you
5
+# think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
6
+# ----------------------------------------------------------------------------
7
+
8
+HOST = iot
9
+
10
+# ----------------------------------------------------------------------------
11
+
12
+# https://tech.davis-hansson.com/p/make/
13
+
14
+SHELL := bash
15
+.ONESHELL:
16
+.SHELLFLAGS := -eu -o pipefail -c
17
+.DELETE_ON_ERROR:
18
+MAKEFLAGS += --warn-undefined-variables
19
+MAKEFLAGS += --no-builtin-rules
20
+
21
+# check for recent make
22
+ifeq ($(origin .RECIPEPREFIX), undefined)
23
+  $(error This Make does not support .RECIPEPREFIX. Please use GNU Make 4.0 or later)
24
+endif
25
+.RECIPEPREFIX = >
26
+
27
+# ----------------------------------------------------------------------------
28
+
29
+all: lights-telegram
30
+
31
+lights-telegram: lights-telegram.go
32
+> CGO_ENABLED=0 go build
33
+
34
+clean:
35
+> rm -rf lights-telegram
36
+
37
+upload: lights-telegram
38
+> ssh $(HOST) sudo systemctl stop lights-telegram
39
+> scp lights-telegram $(HOST):~/bin/lights-telegram/lights-telegram
40
+> sleep 1
41
+> ssh $(HOST) sudo systemctl start lights-telegram
42
+.PHONY: upload
43
+
44
+download:
45
+> scp $(HOST):~/bin/lights-telegram/config.yaml config.yaml
46
+.PHONY: download

+ 4
- 0
README.md View File

@@ -41,6 +41,10 @@ Modify the username and paths in `lights-telegram.service` and the commands belo
41 41
     systemctl daemon-reload
42 42
     systemctl enable --now lights-telegram
43 43
 
44
+You can also look at the log output of the app.
45
+
46
+    journalctl -u lights-telegram -b -f
47
+
44 48
 ## Dependencies
45 49
 
46 50
  * [tgbotapi](https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5)

+ 67
- 7
lights-telegram.go View File

@@ -25,6 +25,7 @@ type Registration struct {
25 25
     Name string `yaml:"name"`
26 26
     Topic string `yaml:"topic"`
27 27
     Values []string `yaml:"values"`
28
+    lastValue string
28 29
 }
29 30
 
30 31
 type Config struct {
@@ -155,7 +156,7 @@ func sendMessage(text string, user int64) {
155 156
     }
156 157
 }
157 158
 
158
-func sendKeyboardReply(name string, chat int64, message int) {
159
+func sendKeyboardReply(text string, name string, chat int64, message int) {
159 160
     var rows [][]tgbotapi.KeyboardButton
160 161
     for reg := range config.Registration {
161 162
         if name == config.Registration[reg].Name {
@@ -168,7 +169,7 @@ func sendKeyboardReply(name string, chat int64, message int) {
168 169
     }
169 170
     keyboard := tgbotapi.NewOneTimeReplyKeyboard(rows...)
170 171
 
171
-    msg := tgbotapi.NewMessage(chat, "Select option below...")
172
+    msg := tgbotapi.NewMessage(chat, text)
172 173
     msg.ReplyToMessageID = message
173 174
     msg.ReplyMarkup = keyboard
174 175
     _, err := bot.Send(msg)
@@ -231,6 +232,13 @@ func register(name string, topic string, values string) error {
231 232
 
232 233
     config.Registration = append(config.Registration, r)
233 234
     writeConfig()
235
+
236
+
237
+    token := mqttClient.Subscribe(topic, 0, onMessageReceived)
238
+    if token.Wait() && token.Error() != nil {
239
+        log.Printf("MQTT sub error: %v", token.Error())
240
+    }
241
+
234 242
     return nil
235 243
 }
236 244
 
@@ -242,8 +250,14 @@ func remove(s []Registration, i int) []Registration {
242 250
 func unregister(name string) error {
243 251
     for reg := range config.Registration {
244 252
         if name == config.Registration[reg].Name {
253
+            token := mqttClient.Unsubscribe(config.Registration[reg].Topic)
254
+            if token.Wait() && token.Error() != nil {
255
+                log.Println("MQTT unsub error: %v", token.Error())
256
+            }
257
+
245 258
             config.Registration = remove(config.Registration, reg)
246 259
             writeConfig()
260
+
247 261
             return nil
248 262
         }
249 263
     }
@@ -282,6 +296,34 @@ func topicForName(name string) string {
282 296
     return "unknown"
283 297
 }
284 298
 
299
+func lastValueForCommand(name string) string {
300
+    ret := ""
301
+
302
+    for reg := range config.Registration {
303
+        if name == config.Registration[reg].Name {
304
+            if len(config.Registration[reg].lastValue) > 0 {
305
+                ret = "Current state: \""
306
+                ret += config.Registration[reg].lastValue
307
+                ret += "\"\n"
308
+            }
309
+            break
310
+        }
311
+    }
312
+
313
+    ret += "Select option below..."
314
+    return ret
315
+}
316
+
317
+func onMessageReceived(client mqtt.Client, message mqtt.Message) {
318
+    log.Printf("MQTT Rx: %s @ %s", message.Payload(), message.Topic())
319
+
320
+    for reg := range config.Registration {
321
+        if config.Registration[reg].Topic == message.Topic() {
322
+            config.Registration[reg].lastValue = string(message.Payload()[:])
323
+        }
324
+    }
325
+}
326
+
285 327
 func main() {
286 328
     err := readConfig()
287 329
     if err != nil {
@@ -305,11 +347,20 @@ func main() {
305 347
     opts.SetPassword(config.Mqtt.Pass)
306 348
 
307 349
     mqttClient = mqtt.NewClient(opts)
308
-    if token := mqttClient.Connect(); token.Wait() && token.Error() != nil {
350
+    token := mqttClient.Connect();
351
+    if token.Wait() && token.Error() != nil {
309 352
         log.Printf("MQTT error: %v", token.Error())
310 353
         os.Exit(1)
311 354
     }
312 355
 
356
+    // Subscribe to registered topics
357
+    for reg := range config.Registration {
358
+        token := mqttClient.Subscribe(config.Registration[reg].Topic, 0, onMessageReceived)
359
+        if token.Wait() && token.Error() != nil {
360
+            log.Printf("MQTT sub error: %v", token.Error())
361
+        }
362
+    }
363
+
313 364
     // Initialize Telegram
314 365
     bot, err = tgbotapi.NewBotAPI(config.Key)
315 366
     if err != nil {
@@ -381,6 +432,10 @@ func main() {
381 432
                                 reply = fmt.Sprintf("Error authorizing ID! %v", err)
382 433
                             } else {
383 434
                                 reply = fmt.Sprintf("Ok, authorized %d.", id)
435
+
436
+                                // also notify user
437
+                                text := "You have now been authorized by the admin. Try /help for commands."
438
+                                sendMessage(text, id)
384 439
                             }
385 440
                         }
386 441
                     } else {
@@ -460,14 +515,19 @@ func main() {
460 515
                         }
461 516
                     } else if isRegisteredCommand(update.Message.Text[1:]) {
462 517
                         reply = ""
463
-                        sendKeyboardReply(update.Message.Text[1:], update.Message.Chat.ID, update.Message.MessageID)
518
+                        text := lastValueForCommand(update.Message.Text[1:])
519
+                        sendKeyboardReply(text, update.Message.Text[1:], update.Message.Chat.ID, update.Message.MessageID)
464 520
                     }
465 521
             }
466 522
         } else {
467
-            log.Printf("Message from unauthorized user. %s %d", update.Message.From.UserName, update.Message.From.ID)
468
-            notifyAdminAuthorization(update.Message.From.ID, update.Message.From.UserName)
523
+            // only request admin-auth when /start has been sent!
524
+            // this avoids most bot spam.
525
+            if update.Message.Text == "/start" {
526
+                log.Printf("Message from unauthorized user. %s %d", update.Message.From.UserName, update.Message.From.ID)
527
+                notifyAdminAuthorization(update.Message.From.ID, update.Message.From.UserName)
469 528
 
470
-            reply = "Sorry, you are not authorized. Administrator confirmation required."
529
+                reply = "Sorry, you are not authorized. Administrator confirmation required."
530
+            }
471 531
         }
472 532
 
473 533
         // send a reply

Loading…
Cancel
Save