Skip to content

Commit

Permalink
Merge pull request #2 from ArtemVladimirov/bac-1
Browse files Browse the repository at this point in the history
bac-1 Added MQTT SSL support
  • Loading branch information
ArtemVladimirov committed Apr 2, 2023
2 parents 0c3b902 + 5ee66bf commit b5effee
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 37 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ Example of config.yml
auto_discovery_topic: homeassistant # Default: homeassistant
auto_discovery_topic_retain: false # Default: true
auto_discovery: true # Default: true
certificate_authority: "./config/cert/ca.crt" # Optional. CA certificate in CRT format.
skip_cert_cn_check: false # Default: true. Don’t verify if the common name in the server certificate matches the value of broker.
## Authorization using client certificates
certificate_client: "./config/cert/client.crt" # Optional
key-client: "./config/cert/client.key" # Optional
devices:
- ip: 192.168.1.12
Expand Down
3 changes: 1 addition & 2 deletions app/mqtt/models/models.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package models

type ConfigMqtt struct {
Host string
Port uint16
Broker string
User *string
Password *string
ClientId string
Expand Down
75 changes: 75 additions & 0 deletions app/mqtt/mqtt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package mqtt

import (
"crypto/tls"
"crypto/x509"
"errors"
"github.com/ArtVladimirov/BroadlinkAC2Mqtt/config"
paho "github.com/eclipse/paho.mqtt.golang"
"github.com/rs/zerolog"
"net/url"
"os"
"time"
)

func NewMqttConfig(logger *zerolog.Logger, cfg config.Mqtt) (*paho.ClientOptions, error) {

//Configure MQTT Client
uri, err := url.Parse(cfg.Broker)
if err != nil {
message := "URL address is incorrect"
logger.Error().Msg(message)
return nil, errors.New(message)
}

opts := paho.NewClientOptions().AddBroker(uri.String()).SetClientID(cfg.ClientId)

if cfg.User != nil {
opts.SetUsername(*cfg.User)
}
if cfg.Password != nil {
opts.SetPassword(*cfg.Password)
}

opts.SetKeepAlive(30 * time.Second)
opts.SetPingTimeout(10 * time.Second)
opts.SetAutoReconnect(true)
opts.SetCleanSession(false)
opts.SetConnectionLostHandler(func(client paho.Client, err error) {
logger.Error().Err(err).Msg("MQTT connection lost")
})
opts.SetOnConnectHandler(func(client paho.Client) {
logger.Info().Err(err).Msg("Connected to MQTT")
})

if uri.Scheme == "mqtts" || uri.Scheme == "ssl" {
tlsConfig := &tls.Config{}

if cfg.CertificateClient != nil && cfg.KeyClient != nil {
cert, err := tls.LoadX509KeyPair(*cfg.CertificateClient, *cfg.KeyClient)
if err != nil {
logger.Fatal().Err(err).Msg("Failed to load the client key pair")
}
tlsConfig.Certificates = []tls.Certificate{cert}
}

if cfg.CertificateAuthority != nil {
caCert, err := os.ReadFile(*cfg.CertificateAuthority)
if err != nil {
logger.Fatal().Err(err).Msg("Failed to load the authority certificate")
}

// Create a certificate pool and add the CA certificate
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)

tlsConfig.RootCAs = caCertPool
}

tlsConfig.InsecureSkipVerify = cfg.SkipCertCnCheck

opts.SetTLSConfig(tlsConfig)
}

return opts, err
}
2 changes: 1 addition & 1 deletion app/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ func (s *service) PublishDiscoveryTopic(ctx context.Context, logger *zerolog.Log
Device: models_mqtt.DiscoveryTopicDevice{
Model: "AirCon",
Mf: "ArtVladimirov",
Sw: "v0.1.0",
Sw: "v1.0.0",
Ids: input.Device.Mac,
Name: input.Device.Name,
},
Expand Down
11 changes: 7 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ type (
}

Mqtt struct {
Host string `env-required:"true" yaml:"host"`
Port uint16 `env-default:"1883" yaml:"port"`
User *string `env-required:"false" yaml:"user"`
Password *string `env-required:"false" yaml:"password"`
Broker string `env-required:"true" yaml:"broker"`
User *string `yaml:"user"`
Password *string `yaml:"password"`
ClientId string `env-default:"broadlinkac" yaml:"client_id"`
TopicPrefix string `env-default:"airac" yaml:"topic_prefix"`
AutoDiscoveryTopic string `env-default:"homeassistant" yaml:"auto_discovery_topic"`
AutoDiscoveryTopicRetain bool `env-default:"true" yaml:"auto_discovery_topic_retain"`
AutoDiscovery bool `env-default:"true" yaml:"auto_discovery"`
CertificateAuthority *string `yaml:"certificate_authority"`
SkipCertCnCheck bool `env-default:"true" yaml:"skip_cert_cn_check"`
CertificateClient *string `yaml:"certificate_client"`
KeyClient *string `yaml:"key-client"`
}

Devices struct {
Expand Down
11 changes: 9 additions & 2 deletions config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@ service:
log_level: error

mqtt:
port: 1883
host: 192.168.1.36
## Use mqtts for SSL support
broker: "mqtt://192.168.1.10:1883"
user: admin
password: password
client_id: aircac2
topic_prefix: aircon2
auto_discovery_topic: homeassistant
auto_discovery_topic_retain: false
auto_discovery: true
## CA certificate in CRT format.
# certificate_authority: "./config/cert/ca.crt"
## Don’t verify if the common name in the server certificate matches the value of broker
# skip_cert_cn_check: true
## Authorization using client certificates
# certificate_client: "./config/cert/client.crt"
# key-client: "./config/cert/client.key"

devices:
- ip: 192.168.1.12
Expand Down
31 changes: 3 additions & 28 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"github.com/ArtVladimirov/BroadlinkAC2Mqtt/app"
"github.com/ArtVladimirov/BroadlinkAC2Mqtt/app/mqtt"
workspaceMqttModels "github.com/ArtVladimirov/BroadlinkAC2Mqtt/app/mqtt/models"
workspaceMqttSender "github.com/ArtVladimirov/BroadlinkAC2Mqtt/app/mqtt/publisher"
workspaceMqttReceiver "github.com/ArtVladimirov/BroadlinkAC2Mqtt/app/mqtt/subscriber"
Expand All @@ -15,10 +16,8 @@ import (
paho "github.com/eclipse/paho.mqtt.golang"
"github.com/rs/zerolog"
"golang.org/x/sync/errgroup"
"net/url"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -58,8 +57,7 @@ func NewApp(logger *zerolog.Logger) (*App, error) {
}

mqttConfig := workspaceMqttModels.ConfigMqtt{
Host: cfg.Mqtt.Host,
Port: cfg.Mqtt.Port,
Broker: cfg.Mqtt.Broker,
User: cfg.Mqtt.User,
Password: cfg.Mqtt.Password,
ClientId: cfg.Mqtt.ClientId,
Expand All @@ -73,30 +71,7 @@ func NewApp(logger *zerolog.Logger) (*App, error) {

cache := workspaceCache.NewCache()

//Configure MQTT Client
uri, err := url.ParseRequestURI("tcp://" + cfg.Mqtt.Host + ":" + strconv.Itoa(int(cfg.Mqtt.Port)))
if err != nil {
message := "URL address is incorrect"
logger.Error().Msg(message)
return nil, errors.New(message)
}
opts := paho.NewClientOptions().AddBroker(uri.String()).SetClientID(cfg.Mqtt.ClientId)
if cfg.Mqtt.User != nil {
opts.SetUsername(*cfg.Mqtt.User)
}
if cfg.Mqtt.Password != nil {
opts.SetPassword(*cfg.Mqtt.Password)
}
opts.SetKeepAlive(30 * time.Second)
opts.SetPingTimeout(10 * time.Second)
opts.SetAutoReconnect(true)
opts.SetCleanSession(false)
opts.SetConnectionLostHandler(func(client paho.Client, err error) {
logger.Error().Err(err).Msg("MQTT connection lost")
})
opts.SetOnConnectHandler(func(client paho.Client) {
logger.Info().Err(err).Msg("Connected to MQTT")
})
opts, _ := mqtt.NewMqttConfig(logger, cfg.Mqtt)
client := paho.NewClient(opts)

//Configure MQTT Sender Layer
Expand Down

0 comments on commit b5effee

Please sign in to comment.