add code
This commit is contained in:
commit
7e7334abe3
136
backend/backend.go
Normal file
136
backend/backend.go
Normal file
@ -0,0 +1,136 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
MQTT "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func createUrl(url string, port int) string {
|
||||
return fmt.Sprintf("tcp://%s:%d", url, port)
|
||||
}
|
||||
|
||||
type message struct {
|
||||
Time time.Time `json:string`
|
||||
Topic string `json:string`
|
||||
Payload string `json:string`
|
||||
}
|
||||
|
||||
func newRecoder(r *os.File, exitSignalCh chan os.Signal) chan MQTT.Message {
|
||||
c := make(chan MQTT.Message)
|
||||
go func() {
|
||||
w := bufio.NewWriter(r)
|
||||
for {
|
||||
select {
|
||||
case toSave := <-c:
|
||||
{
|
||||
now := time.Now()
|
||||
m := message{now,
|
||||
toSave.Topic(),
|
||||
string(toSave.Payload())}
|
||||
mStr, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
log.Print("Problems with a message: topic %s, payload: %s", toSave.Topic(), toSave.Payload())
|
||||
} else {
|
||||
fmt.Fprintf(w, "%+v\n", string(mStr))
|
||||
}
|
||||
}
|
||||
|
||||
case <-exitSignalCh:
|
||||
{
|
||||
fmt.Println("Flushing to disk")
|
||||
w.Flush()
|
||||
r.Close()
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
return c
|
||||
}
|
||||
|
||||
func StartRecording(c *cli.Context) {
|
||||
url := createUrl(c.GlobalString("url"), c.GlobalInt("port"))
|
||||
file, err := os.Create(c.GlobalString("record"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
topic := c.GlobalString("topic")
|
||||
|
||||
opts := MQTT.NewClientOptions()
|
||||
opts.AddBroker(url)
|
||||
|
||||
receiver := MQTT.NewClient(opts)
|
||||
if token := receiver.Connect(); token.Wait() && token.Error() != nil {
|
||||
log.Fatal(token.Error())
|
||||
}
|
||||
exitSignalCh := make(chan os.Signal)
|
||||
signal.Notify(exitSignalCh, os.Interrupt)
|
||||
signal.Notify(exitSignalCh, syscall.SIGTERM)
|
||||
|
||||
recoderCh := newRecoder(file, exitSignalCh)
|
||||
f := func(receiver MQTT.Client, msg MQTT.Message) {
|
||||
recoderCh <- msg
|
||||
}
|
||||
|
||||
if token := receiver.Subscribe(topic, 1, f); token.Wait() && token.Error() != nil {
|
||||
log.Fatal(token.Error())
|
||||
}
|
||||
|
||||
for {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func PlayBack(c *cli.Context) {
|
||||
url := createUrl(c.GlobalString("url"), c.GlobalInt("port"))
|
||||
|
||||
opts := MQTT.NewClientOptions()
|
||||
opts.AddBroker(url)
|
||||
|
||||
sender := MQTT.NewClient(opts)
|
||||
if token := sender.Connect(); token.Wait() && token.Error() != nil {
|
||||
log.Fatal(token.Error())
|
||||
}
|
||||
playLoop := c.Bool("loop")
|
||||
loopCount := 0
|
||||
for playLoop || loopCount == 0 {
|
||||
loopCount++
|
||||
file, err := os.Open(c.GlobalString("record"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
reader := bufio.NewScanner(file)
|
||||
fastForward := c.Bool("ff")
|
||||
var message message
|
||||
var previousTime time.Time
|
||||
firstRound := true
|
||||
for reader.Scan() {
|
||||
json.Unmarshal([]byte(reader.Text()), &message)
|
||||
if !fastForward {
|
||||
if !firstRound {
|
||||
toWait := message.Time.Sub(previousTime)
|
||||
previousTime = message.Time
|
||||
time.Sleep(toWait)
|
||||
} else {
|
||||
firstRound = false
|
||||
previousTime = message.Time
|
||||
}
|
||||
}
|
||||
fmt.Println(message.Payload)
|
||||
if token := sender.Publish(message.Topic, 1, false, message.Payload); token.Wait() && token.Error() != nil {
|
||||
fmt.Println(token.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
73
main.go
Normal file
73
main.go
Normal file
@ -0,0 +1,73 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/siscia/mqtt-player/backend"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "mqtt-player"
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "record",
|
||||
Usage: "What file use to record and playback",
|
||||
Value: "mqtt-record.txt",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "topic",
|
||||
Usage: "What topic listen and what topic play back",
|
||||
Value: "/#",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "url",
|
||||
Usage: "Where to listen to the MQTT broker",
|
||||
Value: "localhost",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "What port to use to connect to the broker",
|
||||
Value: 1883,
|
||||
},
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "record",
|
||||
Aliases: []string{"r", "rec"},
|
||||
Usage: "Record traffic from a MQTT broker",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println(c.GlobalString("url"))
|
||||
backend.StartRecording(c)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "play",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "Play back previous registered traffic to a MQTT broker",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Playing back the recorded traffic from: ", c.GlobalString("record"))
|
||||
backend.PlayBack(c)
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "ff",
|
||||
Usage: "Fast forward, if true plays all the messages in the file without respecting the times differences"},
|
||||
|
||||
cli.BoolFlag{
|
||||
Name: "loop",
|
||||
Usage: "Loop the player and keep playing all the messages, in order, indefinitely",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user