TuyaLink-Based Devices

Last Updated on : 2024-03-04 07:31:45

TuyaLink is an open solution that enables IoT devices, including proprietary network modules and smart devices, to connect to Tuya’s cloud services. TuyaLink allows you to quickly integrate with the Tuya ecosystem and achieve interconnectivity between devices across different domains. A range of development resources for PaaS, SaaS, and apps helps you implement IoT projects with improved cost efficiency and reduced lead time. For more information, see TuyaLink.

Identify TuyaLink-based device

API description

- (BOOL)isSupportThingModelDevice;

Example

Objective-C:

- (void)judgeSupportThingLink {
    // self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];

    BOOL isSupport = [self.device.deviceModel isSupportThingModelDevice];
    NSLog(@"judgeSupportThingLink: %ld", isSupport);
}

Swift:

func judgeSupportThingLink() {
    let isSupport = device?.deviceModel?.isSupportThingModelDevice()
}

Things data model

The device model construct describes an abstraction of physical devices. It defines the characteristics and behaviors of a type of device that connects to the cloud. This model defines an abstract representation of a device as a set of properties, actions, and events, and determines how a connected physical device interacts with the cloud applications.

Type Description Scenario
Property The property type is used to define the continuous and queryable states of a device, which can represent one or several feature parameters. A property can be read-write or read-only for data update and query. When a specific feature parameter is updated, the device can update the property accordingly. For example, a light bulb might have properties like power state and brightness.
Action The action type is used to run complex tasks. An action command is not intended to change the device property, but directs the device to return a response. For example, face recognition and picture transmission.
Event The event type is used to define a live notification reported by a device, which requires external sensing and processing. Events work with message subscription or rule engines to respond as per the predefined logic. For example, overheating alerts and fault alerts.

Currently, things data models are returned on demand from a local cache. To keep the cached data up to date, you need to timely pull the latest things data model and update the cache.

API description

@interface ThingSmartDeviceModel
// ....

// Returns the locally cached things data model.
@property (nonatomic, strong, nullable) ThingSmartThingModel *thingModel;
@end

@interface ThingSmartDevice
// ...

// Pulls the latest things data model that matches current device information and updates the cached data.
- (void)getThingModelWithSuccess:(nullable void(^)(ThingSmartThingModel * _Nullable thingModel))success
                         failure:(nullable ThingFailureError)failure;

// Pulls the latest things data model that matches the specified product ID (PID) and PID version and updates the cached data.
+ (void)getThingModelWithProductId:(NSString *)pid
                    productVersion:(NSString *)productVersion
                           success:(nullable void (^)(ThingSmartThingModel * _Nullable thingModel))success
                           failure:(nullable ThingFailureError)failure;
@end

Data model of ThingSmartThingModel

Field Type Description
modelId NSString The ID of the things data model.
productId NSString The product ID (PID).
productVersion NSString The version of the PID.
services NSArray<ThingSmartThingServiceModel *> The service model.
extensions NSDictionary The extension information.

Data model of ThingSmartThingServiceModel

Field Type Description
properties ThingSmartThingProperty The list of properties.
actions ThingSmartThingAction The list of actions.
events ThingSmartThingEvent The list of events.

Data model of ThingSmartThingProperty

Field Type Description
abilityId NSInteger The property ID can be regarded as dpId of dps for a generic device.
code NSString The code of the specified property.
accessMode NSString The access mode. Valid values:
  • rw: send and report
  • ro: report only
  • wr: send only
typeSpec NSDictionary The definition of a data type.
defaultValue id The default value.

Description

Currently, typeSpec supports the following data types: value, string, date, bool, enum, fault (bitmap), array, and struct.

The array and struct types are dedicated for TuyaLink. struct is a nested type that encloses other type definitions.

Examples of data types

// type = value
{
  "unit" : "℃",
  "type" : "value",
  "min" : 0,
  "max" : 100,
  "typeDefaultValue" : 0,
  "step" : 1,
  "scale" : 1
}

// type = string
{
  "type" : "string",
  "typeDefaultValue" : "",
  "maxlen" : 50
}

// date
{
  "type" : "date",
  "typeDefaultValue" : 1658482441413
}

// bool
{
  "type" : "bool",
  "typeDefaultValue" : false
}

// enum
{
  "range" : [
    "e1",
    "e2",
    "e3"
  ],
  "typeDefaultValue" : "e1",
  "type" : "enum"
}

// fault (bitmap)
{
  "label" : [
    "f1",
    "f2"
  ],
  "typeDefaultValue" : 0,
  "type" : "bitmap"
}

// array
{
  "maxSize" : 4,
  "type" : "array",
  "elementTypeSpec" : {
    "type" : "value"
  }
}

// struct
{
  "type" : "struct",
  "properties" : {
    "struct_value" : {
      "name" : "test_value",
      "typeSpec" : {
        "type" : "value",
        "min" : 11,
        "typeDefaultValue" : 11,
        "max" : 22,
        "step" : 2,
        "scale" : 1
      }
    }
  }
}

Data model of ThingSmartThingAction

Field Type Description
abilityId NSInteger The action ID.
code NSString The action code.
inputParams NSArray The list of parameters to be sent.
outputParams NSArray The list of parameters to be reported.

inputParams and outputParams are arrays of typeSpec and can be empty. Example:

// input
{
  "code": "action_input_output_params",
  "abilityId" : 108,

  "inputParams" : [{
    "typeSpec" : {
      "unit" : "¥",
      "type" : "value",
      "min" : 0,
      "max" : 5,
      "typeDefaultValue" : 0,
      "step" : 1,
      "scale" : 0
    },
    "code" : "action_value"
  },
  {
    "typeSpec" : {
      "type" : "string",
      "typeDefaultValue" : "",
      "maxlen" : 100
    },
    "code" : "action_string"
  }],

  "outputParams" : [{
    "typeSpec" : {
      "unit" : "$",
      "type" : "value",
      "min" : 0,
      "max" : 100,
      "typeDefaultValue" : 0,
      "step" : 1,
      "scale" : 0
    },
    "code" : "out_action_value"
  }]
}

Data model of ThingSmartThingEvent

Field Type Description
abilityId NSInteger The event ID.
code NSString The event code.
outputParams NSArray The list of parameters to be reported.

Control devices

Send commands

API description

- (void)publishThingMessageWithType:(ThingSmartThingMessageType)thingMessageType
                            payload:(NSDictionary *)payload
                            success:(ThingSuccessHandler)success
                            failure:(ThingFailureError)failure

Parameters

Parameter Type Description
thingMessageType ThingSmartThingMessageType
  • 0: property
  • 1: action
  • 2: event
payload NSDictionary The content to be sent.
success ThingSuccessHandler The success callback.
failure ThingFailureError The failure callback.
  • The content validity is checked to send a command. Therefore, the things data model must be cached in this process. You need to timely check and pull the latest things data model.
  • To support the features of TuyaLink-based devices, they can be controlled over MQTT only.
  • The events in ThingSmartThingMessageType can only be reported, which means they are read-only and cannot be changed.

The following examples show the payload format.

  • Rules of sending properties

    // Multiple properties can be sent simultaneously. code is the property code in a things data model. value is subject to the definition of typeSpec.
    {
        "code": value,
        "code": value
    }
    
    // Example:
    {
        "color":"green",
        "brightness": 50
    }
    
  • Rules of sending an action

    // Only one action can be sent at a time.
    {
    "actionCode": "code",
    "inputParams": {
        "paramsCode": value,
        "paramsCode": value,
    }
    }
    
    // Example:
    {
        "actionCode": "action_input_output_params",
        "inputParams": {
            "action_value": 5,
            "action_string": "test_string"
        }
    }
    

Example

Objective-C:

// Pulls the latest things data model at the right time, for example, when users tap a device to go to the device control page.
- (void)fetchThingModel {
    // self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];

    if (!self.device.deviceModel.thingModel) {
      [self.device getThingModelWithSuccess:^(ThingSmartThingModel * _Nullable thingModel) {
          NSLog(@"fetch thing model success: %@", thingModel);
      } failure:^(NSError *error) {
          NSLog(@"fetch thing model fail: %@", error);
      }];
    }
}

// Device control: send properties
// Note: deviceModel.thingModel must exist before properties are sent.
- (void)publishProperty {
    // self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];

      // Sends properties.
      NSDictionary *propertyPayload = @@{
        @"color": @"green",
        @"brightness": @50
    };
        [self.device publishThingMessageWithType:ThingSmartThingMessageTypeProperty payload:propertyPayload success:^{
        NSLog(@"success");
    } failure:^(NSError *error) {
        NSLog(@"failure: %@", error);
    }];
}

// Device control: send an action
// Note: deviceModel.thingModel must exist before properties are sent.
- (void)publishAction {
    // self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];

      // Sends an action.
        NSDictionary *actionPayload = @{
        @"actionCode": @"action_input_output_params",
        @"inputParams": @{
            @"action_value": @5,
            @"action_string": @"test_string"
        }
    };
      [self.device publishThingMessageWithType:ThingSmartThingMessageTypeAction payload:actionPayload success:^{
        NSLog(@"success");
    } failure:^(NSError *error) {
        NSLog(@"failure: %@", error);
    }];
}

Swift:

// Pulls the latest things data model at the right time, for example, when users tap a device to go to the device control page.
func fetchThingModel() {
  device?.getThingModel(success: { thingModel in
      print("success \(thingModel)")
  }, failure: { error in
      if let err = error {
          print("failure \(err)")
      }
  })
}

// Device control: send properties
// Note: deviceModel.thingModel must exist before properties are sent.
func publishProperty() {
  let porpetyPayload = [
    "color": "green",
    "brightness": 50
  ]
  device?.publishThingMessage(with: .property, payload: porpetyPayload, success: {
    print("publish property success")
  }, failure: { error in
    if let err = error {
      print("publish property fail.(%@)", err)
    }
  })
}

func publishAction() {
  let actionPayload = [
    "actionCode": "action_input_output_params",
    "inputParams": [
      "action_value": 5,
      "action_string": "test_string"
    ]
  ]
  device?.publishThingMessage(with: .action, payload: actionPayload, success: {
    print("publish action success")
  }, failure: { error in
    if let err = error {
      print("publish action fail.(%@)", err)
    }
  })
}

Listen for the callback

You can use ThingSmartDevice to set a delegate and listen for the callback.

API description

- (void)device:(ThingSmartDevice *)device didReceiveThingMessageWithType:(ThingSmartThingMessageType)thingMessageType payload:(NSDictionary *)payload;

Parameters

Parameter Type Description
device ThingSmartDevice The device object to be operated.
ThingSmartThingMessageType ThingSmartThingMessageType
  • 0: property
  • 1: action
  • 2: event
payload NSDictionary The reported content that is received. The format can vary, depending on the different values of thingMessageType. For more information, see the examples below in things to note.
  • The content validity is checked to report status data. Therefore, the things data model must be cached in this process. You need to timely check and pull the latest things data model.
  • The property messages will be converted into the dps format, and the callback will be returned by -device:dpsUpdate:.

The following examples show the payload format that varies depending on different message types.

  • Report device properties

    // Rules of the format
    {
    "code": {
        "value": value,
        "time": 1234567890
    },
    "code": {
        "value": value,
        "time": 1234567890
    }
    }
    
    // Example:
    {
        "color": {
            "value": "green",
            "time": 1234567890
        },
        "brightness": {
            "value": 50,
            "time": 1234567890
        }
    }
    
  • Report an action

    // Rules of the format
    {
        "actionCode": code,
        "outputParams": {
            "outputParam1": value,
            "outputParam2": value
        }
    }
    
    // Example:
    {
        "actionCode": "open_door_action",
        "outputParams": {
            "status": "open",
            "angle": 30
        }
    }
    
  • Report an event

    // Rules of the format
    {
        "eventCode": code,
        "outputParams": {
            "outputParam1": value,
            "outputParam2": value
        }
    }
    
    // Example:
    {
        "eventCode": "people_move_event",
        "outputParams": {
            "count": 2,
            "time": "2022-07-22 18:30:00"
        }
    }
    

Example

Objective-C:

// Listens for the callback at the right time.
- (void)addThingDeviceListner {
      // self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
      device.delegate = self;
}

// Note: deviceModel.thingModel must exist before the reported content is received.
- (void)device:(ThingSmartDevice *)device didReceiveThingMessageWithType:(ThingSmartThingMessageType)thingMessageType payload:(NSDictionary *)payload {

    NSLog(@"---did receive thing msg type: %ld, msg: %@", thingMessageType, payload);
    // The payload format can vary, depending on different values of type. For more information, see the parameter description.
    if (thingMessageType == ThingSmartThingMessageTypeProperty) {
        //.. do something
    } else if (thingMessageType == ThingSmartThingMessageTypeAction) {
        //.. do something
    } else if (thingMessageType == ThingSmartThingMessageTypeEvent) {
        //.. do something
    }
}

Swift:

// Listens for the callback at the right time.
func addThingDeviceListner {
  device?.delegate = self;
}

// Note: deviceModel.thingModel must exist before the reported content is received.
func device(_ device: ThingSmartDevice, didReceiveThingMessageWith thingMessageType: ThingSmartThingMessageType, payload: [AnyHashable : Any]) {
  print("---did receive thing msg type: \(thingMessageType), payload: \(payload)")
  switch thingMessageType {
  case .property:
    //.. do something
  case .action:
    //.. do something
  case .event:
    //.. do something
  }
}

Cached payload of property, action, and event

For a things data model, the property represents the continuous and queryable states of a device. The action and event represent the real-time responses of a device. Therefore, the cache rules for each message payload are described as follows:

  • The property is cached. ThingSmartDeviceModel::dps can be used to get the cached content.
  • The action is not cached.
  • The event is not cached.

The property is defined in the same way as the data point (DP) of a generic device. Therefore, the property can be cached based on ThingSmartDeviceModel::dps. Format: dpId = value.

The property is displayed based on the mappings of ThingSmartThingProperty::abilityId in the property model.

Convert property payload to DP

The properties of a TuyaLink-based device are defined in the same way as the DP of a generic device. The difference is that array and struct are added as new types for TuyaLink.

When reported property messages are received, a callback is returned by -device:didReceiveThingMessageWithType:payload:. Meanwhile, the property is converted to dps, and a callback is returned by -device:dpsUpdate:. The returned content is cached in deviceModel.dps and deviceModel.dpsTime.

You can also convert the property to the DP by using the method -dpsFromProperties: opened in ThingSmartThingModel.

API description

@interface ThingSmartThingModel : NSObject
//...

// Converts the property to the DP.
- (NSDictionary *)dpsFromProperties:(NSDictionary *)properties;
@end

Parameters

Parameter Type Description
properties NSDictionary The property payload, in the same format as that of the reported property,

Format of the property payload:

{
  "code": {
    "value": value,
    "time": time
  },
  "code": {
    "value": value,
    "time": time
  },
}

Example

Objective-C:

- (void)transferPropertiesToDp {
      ThingSmartThingModel *thing = self.device.deviceModel.thingModel;

      NSDictionary *propertiesPayload = @{
        @"color": @"green",
        @"brightness": @50
    }
    NSDictionary *dps = [thing dpsFromProperties:propertiesPayload];
    NSLog(@"---- dps: %@", dps);

      /**
          In the output, 101 and 105 respectively represent color and brightness of ThingSmartThingProperty::abilityId.
          @{
              @"101": @"green",
              @"105": @50
          }
      */
}

Swift:

func trnasferPropertiesToDp {
  if let thing = device?.deviceModel.thingModel {
    let propertiesPayload = [
      "color": "green",
      "brightness": 50
    ]
    let dps = thing?.dps(fromProperties: propertiesPayload)
    print("--- dps: \(dps)")
  }
}