Aliyun IoT .NET Core Client | CZGL.AliIoTClient: 7. Service Invocation

2019年12月15日 20点热度 0人点赞 0条评论
内容目录

Document Directory:


 

Code that is pre-written on the device can handle one or more tasks, which is referred to as a service, where a service consists of one or more tasks.

In CZGL.AliIoTClient, there is no need to configure the service invocation commands issued by the server; by default, the server can issue commands without needing client consent.
Although the client can directly receive service invocation commands from the server, it must set appropriate methods bound to the delegation to handle the commands.

Below is an example to illustrate how to use service invocation:

  1. The device defines a service, which is a timed explosion.
  2. When the explosion command and the timed explosion duration issued by the server are received, the task begins.
  3. After the explosion, the explosion result is returned.
  4. The server issues a command to the device to make it explode.
  5. The server does not care how the device explodes, nor does it wait for the explosion.
  6. Once the device has completed the explosion, it informs the server that the explosion has finished.

1) Set Up Service Invocation

Open the Alibaba Cloud IoT Console, click on Custom Function, and follow the definitions below.

Service Definition:

Define Service

Input Parameters:

Set Input Parameters

Output Parameters:

Get Output Parameters


2) Service Definition Description

The defined service has input parameters and output parameters, which refers to the commands issued by the server to invoke the service on the device. This includes the input parameters needed for the service and the parameters returned after invoking the service.
This is relative to the device; the server calls the device's service, sends data (input parameters) to the device, and then the device processes and returns the result (output parameters).

There are asynchronous and synchronous methods available; using an asynchronous method, the server does not need to wait for the device to respond and can return directly.
Using a synchronous method, the server must wait for a response, and if no result is obtained within a time limit, it will report a timeout error.

The basic test code used is as follows (please replace the values of DeviceOptions):

        static AliIoTClientJson client;
        static void Main(string[] args)
        {
            // Create client
            client = new AliIoTClientJson(new DeviceOptions
            {
                ProductKey = "a1A6VVt72pD",
                DeviceName = "json",
                DeviceSecret = "7QrjTptQYCdepjbQvSoqkuygic2051zM",
                RegionId = "cn-shanghai"
            });
        client.OpenPropertyDownPost();
        // Set the Topic to subscribe to and the Topic to receive content
        string[] topics = new string[] { client.CombineHeadTopic("get") };
        // Use default event
        client.UseDefaultEventHandler();
        // Connect to server
        client.ConnectIoT(topics, null, 60);
        Console.ReadKey();
    }

Run the console program, open Alibaba Cloud IoT Console, online debugging, find the service, choose Machine Auto Explosion
Input the following content in the input box:

{
    "timee":10
}

Click send, then check the console output.

{"method":"thing.service.bom","id":"670534570","params":{"timee":10},"version":"1.0.0"}

According to the definition and requirements, once the service invocation command is actually received, it needs to be processed and the response result returned.


3) Write Reception Model and Response Model

The received message is Alink JSON, and you can convert it into the corresponding object using CZGL.AliIoTClient.
Similarly, you will also need to convert the corresponding object back to Alink JSON to upload to the server as a response.

Write the reception model: it contains a very simple parameter timee, which corresponds to the input parameter defined in the console.

        public class Bom
        {
            public string method { get { return "thing.service.bom"; } set { } }
            public string id { get; set; }
            public string version { get { return "1.0.0"; } set { } }
            public Params @params { get; set; }
            public class Params
            {
                public int timee { get; set; }
            }
            public Bom()
            {
                @params = new Params();
            }
        }

Write the response model:

    public class ReBom
        {
            public string id { get; set; }
            public int code { get; set; }
            public Data data { get; set; }
            public class Data
            {
                public int isbom { get; set; }
            }
            public ReBom()
            {
                data = new Data();
            }
        }

4) Define Delegate Method

In CZGL.AliIoTClient, there is a PubServiceEventHandler delegate that triggers a response event when the service invocation command is received from the server.

Therefore, we write a method to process the command and define a custom delegate method.

Service invocation method:

        /// <summary>
        /// Service invocation method
        /// </summary>
        /// <param name="timee"></param>
        /// <returns></returns>
        public static bool BomServer(int timee)
        {
            Console.WriteLine($"I will explode in {timee} seconds");
            /*
             *  Other code *
             */
            // Return processing result, exploded
            return true;
        }

Write the delegate method: outline how to handle when the service invocation command is received.

        /// <summary>
        /// Received service invocation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void Service_Bom_EventHandler(object sender, MqttMsgPublishEventArgs e)
        {
            // Handle message received
            string topic = e.Topic;
            string message = Encoding.ASCII.GetString(e.Message);
            if (topic.Contains("bom"))
            {
                // Convert the received service invocation data into an object
                var model = client.Thing_Service_JsonToObject<Bom>(message);
            // Get the timee parameter from inside, pass this parameter to the method for processing
            var re = BomServer(model.@params.timee);

            // Prepare the information to return
            var reModel = new ReBom()
            {
                code = 200,
                id = model.id
            };
            reModel.data.isbom = 1;

            // Respond to the server and return the processing result
            client.Thing_Service_Identifier_Reply&lt;ReBom&gt;(reModel, "bom", false);
        }
    }

If you have multiple services, you can simply add conditions in the example method Service_Bom_EventHandler provided above.

总之,这些是自定义的,灵活性很高,CZGL.AliIoTClient 负责将你的数据处理以及进行上传下达,但是如何处理指令,需要你编写相应的处理方法。


5)绑定到委托中

在连接服务器前,绑定到委托中

            client.PubServiceEventHandler += Service_Bom_EventHandler;
            // 连接服务器
            client.ConnectIoT(topics, null, 60);

就这么一句代码而已。

当然, CZGL.AliIoTClient 默认有一些方法,在收到服务器消息时触发,这些不会影响到你的委托方法。
如果你不需要,去除即可。

            // 使用默认事件
            // client.UseDefaultEventHandler();

            client.PubServiceEventHandler += Service_Bom_EventHandler;
            // 连接服务器
            client.ConnectIoT(topics, null, 60);

至此,完整的代码如下:

    class Program
    {
        static AliIoTClientJson client;
        static void Main(string[] args)
        {
            // 创建客户端
            client = new AliIoTClientJson(new DeviceOptions
            {
                ProductKey = "a1A6VVt72pD",
                DeviceName = "json",
                DeviceSecret = "7QrjTptQYCdepjbQvSoqkuygic2051zM",
                RegionId = "cn-shanghai"
            });

            client.OpenPropertyDownPost();
            // 设置要订阅的Topic、运行接收内容的Topic
            string[] topics = new string[] { client.CombineHeadTopic("get") };
            // 使用默认事件
            client.UseDefaultEventHandler();

            client.PubServiceEventHandler += Service_Bom_EventHandler;
            // 连接服务器
            client.ConnectIoT(topics, null, 60);
            Console.ReadKey();
        }

        /// <summary>
        /// 收到服务调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void Service_Bom_EventHandler(object sender, MqttMsgPublishEventArgs e)
        {
            // handle message received
            string topic = e.Topic;
            string message = Encoding.ASCII.GetString(e.Message);
            if (topic.Contains("bom"))
            {
                // 将收到的服务调用数据转为对象
                var model = client.Thing_Service_JsonToObject<Bom>(message);

                // 获取里面的timee参数,将这个参数传入给方法进行处理
                var re = BomServer(model.@params.timee);

                // 设置要返回的信息
                var reModel = new ReBom()
                {
                    code = 200,
                    id = model.id
                };
                reModel.data.isbom = 1;

                // 对服务器做出响应,返回处理结果
                client.Thing_Service_Identifier_Reply<ReBom>(reModel, "bom", false);
            }
        }

        public class Bom
        {
            public string method { get { return "thing.service.bom"; } set { } }
            public string id { get; set; }
            public string version { get { return "1.0.0"; } set { } }
            public Params @params { get; set; }
            public class Params
            {
                public int timee { get; set; }
            }
            public Bom()
            {
                @params = new Params();
            }
        }
        public class ReBom
        {
            public string id { get; set; }
            public int code { get; set; }
            public Data data { get; set; }
            public class Data
            {
                public int isbom { get; set; }
            }
            public ReBom()
            {
                data = new Data();
            }
        }
        /// <summary>
        /// 服务调用方法
        /// </summary>
        /// <param name="timee"></param>
        /// <returns></returns>
        public static bool BomServer(int timee)
        {
            Console.WriteLine($"我将在 {timee} 秒后爆炸");
            /*
             * 其它代码 *
             */
            // 返回处理结果,已经爆炸
            return true;
        }
    }

5)服务器下发服务调用指令

运行上面设置的程序,打开阿里云物联网控制台,进入 在线调试。
选择演示的产品、设备,选择上面定义的机器自动爆炸服务。

在文本框输入以下内容

{
    "timee":10
}

点击 发送指令 ,然后点一下 刷新。 可以看到右侧出现了 设备上报数据、云端下发数据

再到设备中,在导航栏点击 服务调用,即可看到调用的服务、传入参数、输出参数等信息。

服务调用结果


6)后续说明

上传响应时,响应的 id 必须与收到的指令 id 一致。

痴者工良

高级程序员劝退师

文章评论