Initializing the PoP process on the tasmota nodes (#243)

* added MQTT lib
* added MQTT config params: domain, port user, password
* sending PoPInit commands to devices par of the pop (after delivery of the PoPInit message)
* Added test case to verify the working of the MQTT connection (test is skipped and designed for manual tests (lack of credentials))
---------

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
This commit is contained in:
Jürgen Eckel 2023-12-20 10:01:28 +01:00 committed by GitHub
parent fd58362a42
commit c09aab8b38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 1 deletions

View File

@ -35,6 +35,10 @@ distribution-address-dao = "{{ .PlmntConfig.DistributionAddrDAO }}"
distribution-address-pop = "{{ .PlmntConfig.DistributionAddrPop }}"
distribution-epochs = {{ .PlmntConfig.DistributionEpochs }}
re-issuance-epochs = {{ .PlmntConfig.ReIssuanceEpochs }}
mqtt-domain = "{{ .PlmntConfig.MqttDomain }}"
mqtt-port = {{ .PlmntConfig.MqttPort }}
mqtt-user = "{{ .PlmntConfig.MqttUser }}"
mqtt-password = "{{ .PlmntConfig.MqttPassword }}"
`
// Config defines Planetmint's top level configuration
@ -62,6 +66,10 @@ type Config struct {
DistributionAddrPop string `json:"distribution-addr-pop" mapstructure:"distribution-addr-pop"`
DistributionEpochs int `json:"distribution-epochs" mapstructure:"distribution-epochs"`
ReIssuanceEpochs int `json:"re-issuance-epochs" mapstructure:"re-issuance-epochs"`
MqttDomain string `json:"mqtt-domain" mapstructure:"mqtt-domain"`
MqttPort int `json:"mqtt-port" mapstructure:"mqtt-port"`
MqttUser string `json:"mqtt-user" mapstructure:"mqtt-user"`
MqttPassword string `json:"mqtt-password" mapstructure:"mqtt-password"`
}
// cosmos-sdk wide global singleton
@ -95,7 +103,16 @@ func DefaultConfig() *Config {
DistributionAddrDAO: "vjU8eMzU3JbUWZEpVANt2ePJuPWSPixgjiSj2jDMvkVVQQi2DDnZuBRVX4Ygt5YGBf5zvTWCr1ntdqYH",
DistributionAddrPop: "vjTvXCFSReRsZ7grdsAreRR12KuKpDw8idueQJK9Yh1BYS7ggAqgvCxCgwh13KGK6M52y37HUmvr4GdD",
DistributionEpochs: 17640, // CometBFT epochs of 5s equate 1 day (12*60*24) + 30 min (12*30) to wait for confirmations on the re-issuance
ReIssuanceEpochs: 17280, // CometBFT epochs of 5s equate 1 day (12*60*24)
// `ReIssuanceEpochs` is a configuration parameter that determines the number of CometBFT epochs
// required for re-issuance. In the context of Planetmint, re-issuance refers to the process of
// issuing new tokens. This configuration parameter specifies the number of epochs (each epoch is 5
// seconds) that need to pass before re-issuance can occur. In this case, `ReIssuanceEpochs` is set
// to 17280, which means that re-issuance can occur after 1 day (12*60*24) of epochs.
ReIssuanceEpochs: 17280,
MqttDomain: "testnet-mqtt.rddl.io",
MqttPort: 1885,
MqttUser: "user",
MqttPassword: "password",
}
}

2
go.mod
View File

@ -15,6 +15,7 @@ require (
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/gogoproto v1.4.10
github.com/cosmos/ibc-go/v7 v7.1.0
github.com/eclipse/paho.mqtt.golang v1.4.3
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3
github.com/gorilla/mux v1.8.0
@ -166,6 +167,7 @@ require (
golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect

3
go.sum
View File

@ -407,6 +407,8 @@ github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB
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/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik=
github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE=
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.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -1185,6 +1187,7 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

53
util/mqtt.go Normal file
View File

@ -0,0 +1,53 @@
package util
import (
"fmt"
"net"
"strconv"
sdk "github.com/cosmos/cosmos-sdk/types"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/planetmint/planetmint-go/config"
"github.com/planetmint/planetmint-go/x/dao/types"
)
func SendMqttMessagesToServer(ctx sdk.Context, challenge types.Challenge) {
err := sendMqttMessages(challenge)
if err != nil {
GetAppLogger().Error(ctx, "MQTT error: "+err.Error())
}
}
func sendMqttMessages(challenge types.Challenge) (err error) {
conf := config.GetConfig()
hostPort := net.JoinHostPort(conf.MqttDomain, strconv.FormatInt(int64(conf.MqttPort), 10))
uri := fmt.Sprintf("tcp://%s", hostPort)
opts := mqtt.NewClientOptions().AddBroker(uri)
opts.SetClientID(conf.ValidatorAddress)
opts.SetUsername(conf.MqttUser)
opts.SetPassword(conf.MqttPassword)
client := mqtt.NewClient(opts)
if token := client.Connect(); token.Wait() && token.Error() != nil {
err = token.Error()
return
}
blockHeight := strconv.FormatInt(challenge.GetHeight(), 10)
token := client.Publish("cmnd/"+challenge.GetChallengee()+"/PoPInit", 0, false, blockHeight)
token.Wait()
err = token.Error()
if err != nil {
return
}
token = client.Publish("cmnd/"+challenge.GetChallenger()+"/PoPInit", 0, false, blockHeight)
token.Wait()
err = token.Error()
if err != nil {
return
}
client.Disconnect(1000)
return
}

22
util/mqtt_test.go Normal file
View File

@ -0,0 +1,22 @@
package util
import (
"testing"
"github.com/planetmint/planetmint-go/x/dao/types"
"github.com/stretchr/testify/assert"
)
func TestSendMqttMessages(t *testing.T) {
t.Parallel()
t.Skip("Skip this test case as this test case expects a working MQTT connection" +
"the test case is intended to work manually.")
var challenge types.Challenge
challenge.Initiator = ""
challenge.Challengee = "plmnt15gdanx0nm2lwsx30a6wft7429p32dhzaq37c06"
challenge.Challenger = "plmnt1683t0us0r85840nsepx6jrk2kjxw7zrcnkf0rp"
challenge.Height = 58
err := sendMqttMessages(challenge)
assert.NoError(t, err)
}

View File

@ -4,6 +4,7 @@ import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/planetmint/planetmint-go/util"
"github.com/planetmint/planetmint-go/x/dao/types"
)
@ -18,5 +19,7 @@ func (k msgServer) InitPop(goCtx context.Context, msg *types.MsgInitPop) (*types
k.StoreChallenge(ctx, challenge)
go util.SendMqttMessagesToServer(ctx, challenge)
return &types.MsgInitPopResponse{}, nil
}