Compare commits

...

4 Commits

7 changed files with 60 additions and 47 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
config.json

1
build.nix Normal file
View File

@ -0,0 +1 @@
with import <nixpkgs> {} ; callPackage ./. { }

5
config.json.example Normal file
View File

@ -0,0 +1,5 @@
{
"smsc": "+447958879879",
"number": "447000123456",
"device": "/dev/serial/by-id/usb-HUAWEI_HUAWEI_HiLink-if00-port0"
}

View File

@ -1,4 +1,9 @@
with import <nixpkgs> {};
{
lua5_3
, stdenv
, fennel
, makeWrapper
}:
let lua = lua5_3.withPackages (ps: [
ps.dkjson
ps.lpeg
@ -6,7 +11,7 @@ let lua = lua5_3.withPackages (ps: [
ps.luaposix
]);
inherit makeWrapper;
fennel = pkgs.fennel.override { inherit lua; };
myfennel = fennel.override { inherit lua; };
in stdenv.mkDerivation {
pname = "grafana-sms-alert";
version = "0.1";
@ -16,9 +21,9 @@ in stdenv.mkDerivation {
lua_path="`lua -e 'print(package.path)'`"
lua_cpath="`lua -e 'print(package.cpath)'`"
makeWrapper ${fennel}/bin/fennel $out/bin/grafana-sms-alert \
makeWrapper ${myfennel}/bin/fennel $out/bin/grafana-sms-alert \
--add-flags "$out/lib/main.fnl"
'';
buildInputs = [lua fennel];
buildInputs = [lua myfennel];
nativeBuildInputs = [ makeWrapper ];
}

View File

@ -1,8 +1,28 @@
(local server (require :server))
(local handler (require :handler))
(local sms (require :sms))
(set _G.modem-spew io.stderr)
(print "Ready")
(doto (server.new handler.handle)
(local server (require :server))
(local webhook (require :webhook))
(local json (require :dkjson))
(local {: smsc : number : device }
(let [filename (assert (. arg 1) "missing argument")
text (with-open [config (io.open filename :r)]
(config:read "*a"))]
(match (json.decode text)
a a
(nil pos err) (error (.. "reading " filename ": " err)))))
(local { : view} (require :fennel))
;(print (view m) (view err))
(local sms ((. (require :sms) :new) { :smsc smsc :device device }))
(doto (server.new
(fn handle [body]
(let [message (webhook.parse body)]
(sms:send number message)
"Sent")))
(: :listen)
(print "server ready")
(: :loop))

33
sms.fnl
View File

@ -54,6 +54,9 @@
(expect fd pattern fail-pattern))
nil)))
(fn command [fd s]
(tx fd (.. s "\r\n"))
(expect fd "OK" "ERROR"))
(fn even? [x]
@ -66,13 +69,11 @@
(test= (phone-number->hex "85291234567") "5892214365F7")
(test= (phone-number->hex "447785016005") "447758100650")
(fn mask [start end]
(let [width (+ 1 (- end start))]
(lshift (rshift 0xff (- 8 width)) start)))
(fn bit-range [i start end]
(rshift (band i (mask start end)) start))
(let [width (+ 1 (- end start))
mask (lshift (rshift 0xff (- 8 width)) start)]
(rshift (band i mask) start)))
(fn septets->hex [body]
;; 0 body0[0-6] | body1[0] << 7
@ -92,7 +93,7 @@
;; nth byte is bits n..6 of nth septet,
;; and bits 0..n of(n+1)th septet
;; for n>=7,
;; for all n including n>=7,
;; bits n%7..6 of floor(n+ (n/7))th septet
;; and 0..(n%7) of the next one
@ -138,10 +139,6 @@
(test= (message->pdu "85291234567" "It is easy to send text messages.") "01000B915892214365F7000021493A283D0795C3F33C88FE06CDCB6E32885EC6D341EDF27C1E3E97E72E")
(fn command [fd s]
(tx fd (.. s "\r\n"))
(expect fd "OK" "ERROR"))
(fn send-message [{: fd} number body]
(let [pdu (message->pdu number (unicode->gsm body))
payload (.. "00" pdu)]
@ -149,7 +146,7 @@
(tx (.. "AT+CMGS=" (string.format "%d" (/ (# pdu) 2)) "\r\n"))
(expect ">" "ERROR")
(tx payload)
(tx "\026\r\n")
(tx "\026")
(expect "OK"))))
(fn new-sender [{: device : smsc : verbose}]
@ -163,15 +160,15 @@
(bnot ISIG)))
(tset termios :oflag (band termios.oflag ( bnot OPOST)))
(doto fd
(tcsetattr 0 termios)
(tcsetattr 0 termios)
(tcdrain)
(command "AT")
(command "AT&F") ; revert to defaults
(command "ATE0") ; disable command echo
(command "AT+CMEE=1") ;print CME errors
(command (.. "AT+CSCA=\"" smsc "\",145\r\n")) ;set SMSC
(command "AT+CMGF=0")) ;SMS PDU mode
(command "AT") ; hello ?
(command "AT&F") ; revert to defaults
(command "ATE0") ; disable command echo
(command "AT+CMEE=1") ; print CME errors
(command (.. "AT+CSCA=\"" smsc "\",145")) ; set SMSC
(command "AT+CMGF=0")) ; expect SMS data in PDU mode
{:send send-message :device device :smsc smsc :fd fd}))

View File

@ -1,26 +1,10 @@
(local json (require :dkjson))
(local unistd (require :posix.unistd))
(local sms
((. (require :sms) :new)
{
:smsc "+447958879879"
:device "/dev/serial/by-id/usb-HUAWEI_HUAWEI_HiLink-if00-port0"
:verbose true
}))
(fn send-sms [body]
(print :send-sms body)
(sms:send "447000123456" body)
"Sent")
(fn handle [s]
(let [(m pos err) (json.decode s 1 nil)]
(fn parse [body]
(let [(m pos err) (json.decode body 1 nil)]
(when m
(send-sms
(.. m.title " " (. (. m.alerts 1) :valueString))))
"ok"))
(.. m.title " " (. (. m.alerts 1) :valueString)))))
;
;;;; {"receiver":"","status":"firing","alerts":[{"status":"firing","labels":{"alertname":"TestAlert","instance":"Grafana"},"annotations":{"summary":"Notification test"},"startsAt":"2022-09-13T21:14:29.77765882+01:00","endsAt":"0001-01-01T00:00:00Z","generatorURL":"","fingerprint":"57c6d9296de2ad39","silenceURL":"http://garf.telent.net:3002/alerting/silence/new?alertmanager=grafana\u0026matcher=alertname%3DTestAlert\u0026matcher=instance%3DGrafana","dashboardURL":"","panelURL":"","valueString":"[ metric='foo' labels={instance=bar} value=10 ]"}],"groupLabels":{},"commonLabels":{"alertname":"TestAlert","instance":"Grafana"},"commonAnnotations":{"summary":"Notification test"},"externalURL":"http://garf.telent.net:3002/","version":"1","groupKey":"{alertname=\"TestAlert\", instance=\"Grafana\"}2022-09-13 21:14:29.77765882 +0100 BST m=+644632.184951212","truncatedAlerts":0,"orgId":1,"title":"[FIRING:1] (TestAlert Grafana)","state":"alerting","message":"**Firing**\n\nValue: [ metric='foo' labels={instance=bar} value=10 ]\nLabels:\n - alertname = TestAlert\n - instance = Grafana\nAnnotations:\n - summary = Notification test\nSilence: http://garf.telent.net:3002/alerting/silence/new?alertmanager=grafana\u0026matcher=alertname%3DTestAlert\u0026matcher=instance%3DGrafana\n"}
{: handle}
{: parse}