WebService的建立
首先,我们需要建立一个本地用C#创建出来的WebService,这里与我之前写的一篇同步调用的文章里的内容是一样的,所以就不再在这里进行过多描述了,可以去我之前的一篇文章里查看相关的建立方法: https://blog.youkuaiyun.com/qq_19408097/article/details/97029286 ,创建Webservice的内容一直到我原来文章的“这段代码的大致解读”为止,之前的都是一样的,从那里之后,我们的内容才会有变化,因为我现在的代码是用的Task的异步调用的方法。
如果已经看过我之前一篇用委托的方式去异步调用的文章的话,我建议还是再看看这篇用Task去异步调用的文章,因为这篇文章增加了新的API,并且提高了他的使用性能和方便性。
然后我们将新的代码复制进去:
using System;
using System.Net;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using System.Web;
using System.Web.Services;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using data;
namespace webservice
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class webservice : System.Web.Services.WebService
{
//register函数是我最初的一个废案,但是想尝试的可以取消这段注释
//static void register(string productKey = "a16wCHCUt1N", string deviceName="computer", string deviceSecret = "0X2g60AxYPrjTJNqbOMrRsQLSc3V1KeR", string regionId = "cn-shanghai")//注册
//{
// reg.ProductKey = productKey;
// reg.DeviceName = deviceName;
// reg.DeviceSecret = deviceSecret;
// reg.RegionId = regionId;
// reg.PubTopic= "/" + productKey + "/" + deviceName + "/user/update";
// reg.SubTopic= "/" + productKey + "/" + deviceName + "/user/get";
//}
[WebMethod(Description = "阿里云发送服务")]
public void access_aliyun_public(int a, string productKey, string deviceName,string deviceSecret, string regionId)//将数据a发送给阿里云平台
{
reg.ProductKey = productKey;
reg.DeviceName = deviceName;
reg.DeviceSecret = deviceSecret;
reg.RegionId = regionId;
reg.PubTopic = "/" + productKey + "/" + deviceName + "/user/update";
reg.SubTopic = "/" + productKey + "/" + deviceName + "/user/get";
Task<string> task = CreateTask(a);
task.Start();//开始任务
task.ContinueWith(t =>
{
common.Number = task.Result;
});
}
[WebMethod(Description = "连接阿里云")]
public void access_aliyun(string productKey, string deviceName, string deviceSecret, string regionId)//登录阿里云
{
reg.ProductKey = productKey;
reg.DeviceName = deviceName;
reg.DeviceSecret = deviceSecret;
reg.RegionId = regionId;
reg.PubTopic = "/" + productKey + "/" + deviceName + "/user/update";
reg.SubTopic = "/" + productKey + "/" + deviceName + "/user/get";
//连接阿里云
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
string clientId = host.AddressList.FirstOrDefault(
ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString();
string t = Convert.ToString(DateTimeOffset.Now.ToUnixTimeMilliseconds());
string signmethod = "hmacmd5";
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("productKey", reg.ProductKey);
dict.Add("deviceName", reg.DeviceName);
dict.Add("clientId", clientId);
dict.Add("timestamp", t);
string mqttUserName = reg.DeviceName + "&" + reg.ProductKey;
string mqttPassword = IotSignUtils.sign(dict, reg.DeviceSecret, signmethod);
string mqttClientId = clientId + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|";
string targetServer = reg.ProductKey + ".iot-as-mqtt." + reg.RegionId + ".aliyuncs.com";
MqttClient client = new MqttClient(targetServer);
client.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
client.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
//订阅消息
var id2 = client.Subscribe(new string[] { reg.SubTopic }, new byte[] { 0 });
}
[WebMethod(Description = "获得数据")]
public string getvalue(string productKey, string deviceName, string deviceSecret, string regionId)//在发送数据以后登录阿里云调用此函数得到刚刚发送的数据
{
Task<string> task = CreateTask2();
task.Start();
return task.Result;
}
static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)//将读取到的数据存到common里面去
{
// handle message received
string topic = e.Topic;
string message = Encoding.ASCII.GetString(e.Message);
common.Name = message;
}
public class IotSignUtils//IoT平台接入password签名算法
{
public static string sign(Dictionary<string, string> param,
string deviceSecret, string signMethod)
{
string[] sortedKey = param.Keys.ToArray();
Array.Sort(sortedKey);
StringBuilder builder = new StringBuilder();
foreach (var i in sortedKey)
{
builder.Append(i).Append(param[i]);
}
byte[] key = Encoding.UTF8.GetBytes(deviceSecret);
byte[] signContent = Encoding.UTF8.GetBytes(builder.ToString());
var hmac = new HMACMD5(key);
byte[] hashBytes = hmac.ComputeHash(signContent);
StringBuilder signBuilder = new StringBuilder();
foreach (byte b in hashBytes)
signBuilder.AppendFormat("{0:x2}", b);
return signBuilder.ToString();
}
}
static Task<string> CreateTask(int a)//创建方法为TaskMethod的Task
{
return new Task<string>(() => TaskMethod(a));
}
static Task<string> CreateTask2()//创建方法为TaskMethod的Task
{
return new Task<string>(() => TaskMethod2());
}
static string TaskMethod(int a)//发送数据、收到数据实现的方法
{
//开始连接阿里云
//register();调用register是一个废案,但是想尝试的可以取消这段注释
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
string clientId = host.AddressList.FirstOrDefault(
ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString();
string t = Convert.ToString(DateTimeOffset.Now.ToUnixTimeMilliseconds());
string signmethod = "hmacmd5";
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("productKey", reg.ProductKey);
dict.Add("deviceName", reg.DeviceName);
dict.Add("clientId", clientId);
dict.Add("timestamp", t);
string mqttUserName = reg.DeviceName + "&" + reg.ProductKey;
string mqttPassword = IotSignUtils.sign(dict, reg.DeviceSecret, signmethod);
string mqttClientId = clientId + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|";
string targetServer = reg.ProductKey + ".iot-as-mqtt." + reg.RegionId + ".aliyuncs.com";
MqttClient client = new MqttClient(targetServer);
client.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
client.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
//发布消息
String content = Convert.ToString(a);
//将string类转换成byte[]
byte[] by1 = System.Text.Encoding.ASCII.GetBytes(content);
var id = client.Publish(reg.PubTopic, by1);
//订阅消息
var id2 = client.Subscribe(new string[] { reg.SubTopic }, new byte[] { 0 });
lop: //子线程里一直等待他的数据回来
if (string.Compare(common.Name, " ") == 0)
goto lop;
else
{
loop:
if (string.Compare(common.Name, Convert.ToString(a)) != 0)
goto loop;
else
return common.Name;
}
}
static string TaskMethod2()//单独获取数据的方法
{
//开始连接阿里云
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
string clientId = host.AddressList.FirstOrDefault(
ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString();
string t = Convert.ToString(DateTimeOffset.Now.ToUnixTimeMilliseconds());
string signmethod = "hmacmd5";
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("productKey", reg.ProductKey);
dict.Add("deviceName", reg.DeviceName);
dict.Add("clientId", clientId);
dict.Add("timestamp", t);
string mqttUserName = reg.DeviceName + "&" + reg.ProductKey;
string mqttPassword = IotSignUtils.sign(dict, reg.DeviceSecret, signmethod);
string mqttClientId = clientId + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|";
string targetServer = reg.ProductKey + ".iot-as-mqtt." + reg.RegionId + ".aliyuncs.com";
MqttClient client = new MqttClient(targetServer);
client.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
client.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
//订阅消息
var id2 = client.Subscribe(new string[] { reg.SubTopic }, new byte[] { 0 });
lop:
if (string.Compare(common.Name, " ") == 0)
goto lop;
else
{
Thread.Sleep(100);
return common.Name;
}
}
}
}
这个代码比我之前写的,不管是同步调用也好,用委托的方式去异步调用也好,都要长的多,主要是因为我将它进行了一定的封装,虽然别人用起来可能会更加方便了一些,但是作为程序员来讲,写代码的时候就要累很多,因为很显然,代码肯定是要变长的。而且这个与我前面几篇的代码不一样的就是,现在这个代码里面并没有自己手动输入自己设备的地方,与设备的绑定是在我已经封装好了的API里面的,所以用起来的时候就更加方便,可以实现在线绑定设备,而不是只能在代码里提前敲好绑定某一个设备,实现了设备的在线绑定这一点。
但是现在代码就目前为止还是会报错的,因为我们还没有写 “data” 这个类。
按下ctrl+shift+A进行页面的添加。选择如下该项:(此处与我原来那篇内容一致,所所以图片我就直接复制过来了)
建立完成以后,将下列代码拷入:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace data
{
public static class common
{
private static string name = " ";
private static string number =" ";
public static string Name
{
get { return name; }
set { name = value; }
}
public static string Number
{
get { return number; }
set { number = value; }
}
}
public static class reg
{
private static string productKey = "";
private static string deviceName = "";
private static string deviceSecret = "";
private static string regionId = "";
private static string pubTopic = "";
private static string subTopic = "";
public static string ProductKey//设置productkey
{
get { return productKey; }
set { productKey = value; }
}
public static string DeviceName//设置divicename
{
get { return deviceName; }
set { deviceName = value; }
}
public static string DeviceSecret//设置devicesecret
{
get { return deviceSecret; }
set { deviceSecret = value; }
}
public static string RegionId//设置regionID
{
get { return regionId; }
set { regionId = value; }
}
public static string PubTopic//设置pubtopic
{
get { return pubTopic; }
set { pubTopic = value; }
}
public static string SubTopic//设置subtopic
{
get { return subTopic; }
set { subTopic = value; }
}
}
}
看过我前面文章的肯定会发现,我这个class里装的都是类似于C#中的全局变量之类的东西,但是我这里多了四个参数。显然的是,这四个参数是用来存设备的参数的。我之前的文章里都没有这个全局变量其实就是因为我没有封装的原因,所以我这四个参数可以放在某一个特定的函数里面,然后函数就可以直接调用就好了,但是因为这里我对程序进行了一定程度的封装,所以其他地方就没有办法调用这个设备的各种参数了,为了解决这个问题,我就采取了这样类全局变量的方法,这样其他的函数,也就能通过调用全局变量的方式,去调用这个设备的参数了。
然后我们运行一下这个程序,可以看到如下界面:
可以看到的是,我这里一共提供了三个WebService的接口,但其实我这三个函数里面,能在这个WebService上产生具体作用的其实就只有access_aliyun和access_aliyun_public函数,getvalue函数在这个页面上是显示不出效果来的,但是这个getvalue函数却是实实在在可以去使用的,我之后会建立一个窗体去调用这个WebService里的这个函数去检验函数是否有效。
我们现在先不管getvalue这个函数,先点开第一个函数:access_aliyun,我们可以看到它会让你输入你要登录的设备的四个参数:
将我们要绑定的设备的四个参数输入完成以后,我们点击调用:
然后我们进入阿里云查看,发现设备已经登陆上去了:
然后我们来测试第二个函数:access_aliyun_public,点击进入后会发现多了一个参数int a,这里输入的参数为数值发出端(不是接收端!)的设备:(这一块关于阿里云上的知识在我之前的文章中有有讲过,不清楚的可以去 https://blog.youkuaiyun.com/qq_19408097/article/details/96452193 查看)
然后我们将数值a和发出端的设备参数输入进去以后,我们点击调用:
然后我们进入阿里云进行数值的查看:
我们可以看见上行消息分析里已经有了发送的数据点开来可以查看到数值:
然后我们点开下行消息分析,也可以看到我们之前写的规则引擎进行了数据传递以后,已经将数据传到了接收端的设备中(computer2),注:这一段的规则引擎不清楚的也可以去我以前写过的一篇文章里查看,地址如下: https://blog.youkuaiyun.com/qq_19408097/article/details/96452193
然后我们就可以看到,下行数据已经确实发送了过去,但是这个数据我们目前还没有将它在除了阿里云以外的地方将它显示出来,所以我在封装API的时候还写了一个getvalue的函数,目的就是为了获得阿里云传递过来的值。我会写一个简单的C#窗体程序来对这个WebService进行一个服务的引用,然后调用这个getvalue函数,但在此之前,我们得先把这个WebService发布出来。
WebService的发布
这一块内容我在之前的文章里已经写过,所以我在这里就不再过多赘述了,读者可以去我之前的文章里查找到这一部分的操作,发布的过程是一模一样的,地址如下: https://blog.youkuaiyun.com/qq_19408097/article/details/97108147
WebService的引用和getvalue函数的测试
这一块内容我会放在下一篇里具体讲,因为我之前写的一篇关于用委托去异步调用的一篇文章里也有这一相同的部分,所以我会放在一起讲,而我举的例子就会是getvalue函数的使用,所以我就不再本篇里描述了,可以去我的下一篇文章里查看相关内容。
本章的内容到这里就结束了,谢谢大家!