tuya-connector-go

module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 17, 2023 License: Apache-2.0

README

English | 中文版

The tuya-connector-go framework maps cloud APIs to local APIs based on simple configurations and flexible extension mechanisms. You can subscribe to the distribution of cloud messages as local events. You can put all the focus on business logic without taking care of server-side programming nor relational databases. The OpenAPI or message subscription process is simplified, so you can focus on service logic and promote development efficiency.

Quick start

Preparation
  • AccessId & AccessKey: the authorization key.
  • API address: Select the API address that is supported by the areas in which your business is deployed.
  • Pulsar address: Select the Pulsar address that is supported by business areas in which your business is deployed.
Configuration
  • Method 1: recommended. Set environment variables, and read the configuration from the environment variables when the project starts.
    export TUYA_API_HOST=https://xxxxx.com
    export TUYA_ACCESSID=xxxxxx
    export TUYA_ACCESSKEY=xxxxxxx
    export TUYA_MSG_HOST=pulsar+ssl://xxxxxx

  • Method 2: Define variables in the project, with hard-coded settings.

Usage
1. Initialize the application (default configuration)
func main() {
   // Default configuration
   connector.InitWithOptions()
   // Start the message subscription service
   go messaging.Listener()
   // Start the API service
   r := router.NewGinEngin()
   go r.Run("0.0.0.0:2021")
   watitSignal()
}

func watitSignal() {
   quitCh := make(chan os.Signal, 1)
   signal.Notify(quitCh, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
   for {
      select {
      case c := <-quitCh:
         extension.GetMessage(constant.TUYA_MESSAGE).Stop()
         logger.Log.Infof("receive sig:%v, shutdown the http server...", c.String())
         return
      }
   }
}

Alternatively, use a custom configuration to initialize the application:

func main() {
   // Custom configuration
   connector.InitWithOptions(env.WithApiHost("xxxx"),
      env.WithMsgHost("xxxx"),
      env.WithAccessID("xxxx"),
      env.WithAccessKey("xxxx"))
   // Start the service
   go messaging.Listener()
   r := router.NewGinEngin()
   go r.Run("0.0.0.0:2021")
   watitSignal()
}
2. Call OpenAPI (taking Gin framework for example)
// Use Gin to create a route
func initRouter(r *gin.Engine) {
   r.GET("/devices/:device_id", GetDevice)
}

func GetDevice(c *gin.Context) {
   device_id := c.Param("device_id")
   resp := &GetDeviceResponse{}
   // Initiate an API request
   err := connector.MakeGetRequest(
      context.Background(),
      connector.WithAPIUri(fmt.Sprintf("/v1.0/devices/%s", device_id)),
      connector.WithResp(resp))
   if err != nil {
      fmt.Println("err:", err.Error())
      c.Abort()
      return
   }
   c.JSON(200, resp)
}

// Data structure returned by OpenAPI
type GetDeviceResponse struct {
   Code    int         `json:"code"`
   Msg     string      `json:"msg"`
   Success bool        `json:"success"`
   Result  interface{} `json:"result"`
   T       int64       `json:"t"`
}

When you call OpenAPI, you can customize the processing logic according to different error codes. You need to create the struct class that implements the IError interface.

type DeviceError struct {
}

func (d *DeviceError) Process(ctx context.Context, code int, msg string) {
   logger.Log.Error(code, msg)
}
func GetDevice(c *gin.Context) {
   device_id := c.Param("device_id")
   resp := new(map[string]interface{})
   err := connector.MakeGetRequest(
      context.Background(),
      connector.WithAPIUri(fmt.Sprintf("/v1.0/devices/%s", device_id)),
      connector.WithResp(resp),
      // Set custom event handling according to error codes
      connector.WithErrProc(1102, &DeviceError{}))
   if err != nil {
      fmt.Println("err:", err.Error())
      c.Abort()
      return
   }
   c.JSON(200, resp)
}
3. Subscribe to message events
func Listener() {
   // Initialize the message queue client
   extension.GetMessage(constant.TUYA_MESSAGE).InitMessageClient()
   // The message event that the specified device changes the name
   extension.GetMessage(constant.TUYA_MESSAGE).SubEventMessage(func(m *event.NameUpdateMessage) {
      logger.Log.Info("=========== name update: ==========")
      logger.Log.Info(m)
   })
   // The message event that the specified device reports data
   extension.GetMessage(constant.TUYA_MESSAGE).SubEventMessage(func(m *event.StatusReportMessage) {
      logger.Log.Info("=========== report data: ==========")
      for _, v := range m.Status {
         logger.Log.Infof(v.Code, v.Value)
      }
   })
}

Custom extension implementation

  • IError interface

    When an error code is returned after you request OpenAPI, you can customize the struct that implements IError to deal with different error codes.

  • IToken interface

    Support the token struct to customize IToken, manage the token lifecycle, get or refresh the token, and locally cache the token information. The object is injected into the underlying framework when the service is initialized.

    extension.GetToken(constant.CUSTOM_TOKEN)
    
  • IHeader interface

    Support the custom header struct. Customize processing logic when you request Tuya IoT Cloud OpenAPI, including attribute values and signatures that need to be added. The object is injected into the underlying framework when the service is initialized.

    extension.GetHeader(constant.CUSTOM_HEADER)
    
  • ISign interface

    Customize the signature logic with the ISign interface. The object is injected into the underlying framework when the service is initialized.

    extension.GetSign(constant.CUSTOM_SIGN)
    
  • IEventMessage interface

    Customize the message event subscription. The connection methods, receiving messages, and data decryption may be different for message queues. In this case, you need to customize the message subscription logic. The object is injected into the underlying framework when the service is initialized.

    extension.GetMessage(constant.CUSTOM_MESSAGE)
    

Message subscription

You can add the processing function for required events. The framework includes all Tuya's cloud message event types. The message data contains ciphertext messages and plaintext messages.

Message event BizCode Description
StatusReportMessage statusReport Report data to the cloud.
OnlineMessage online A device is online.
OfflineMessage offline A device is offline.
NameUpdateMessage nameUpdate Modify the device name.
DpNameUpdateMessage dpNameUpdate Modify the name of a data point.
DeleteMessage delete Remove a device.
BindUserMessage bindUser Bind the device to a user account.
UpgradeStatusMessage upgradeStatus The update status.
AutomationExternalActionMessage automationExternalAction Automate an external action.
SceneExecuteMessage sceneExecute Execute a scene.

Architecture of the framework

Integration of the framework Integration and extensions

Core module design

Design description

Technical support

You can get technical support from Tuya in the following services:

Directories

Path Synopsis
env

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL