吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5912|回复: 19
收起左侧

[其他转载] C# 物联网智能模块管理端开发接口API实例源码分享

[复制链接]
X5ZJ 发表于 2020-8-14 10:06
本帖最后由 X5ZJ 于 2020-8-14 10:21 编辑

近段时间一直研究8266,功能基本实现完毕,开始考虑如何验证设备,管理设备,故开始通过结合数据库进行设备识别认证(前提自建服务器,供物联网模块运行)本帖子仅提供学习思路,有需要的可以参考学习下。大神路过不喜勿喷,违规联系删
一篇文章很长。刚才排版错乱了(浏览器一直卡顿),还要重新编辑,部分文字省略,代码里基本都注释了。不懂的可以留言交流!!



开发目的:

在DIY项目过程中,对于一些小伙伴会进行二次开发,提供一系列的处理方法,故制作本系列教程,以便更好分享,为更加方便小伙伴们的学习。

准备:vs2008/vs2010/vs2013/vs2015/vs2017等等均可。根据项目复杂度和系统配置适合自己的开发环境,本作者选择的是VS2008+.Net framework3.0

步骤:

1)环境安装省略,网上很多。

2)打开VS2008

3)文件》新建》文件》选择“一般处理程序”,起个名字,例如“WebSite_9ibox”

tip:根据您掌握的程度,可以选择不同的文件类型,因为不需要界面,仅提供接口处理,故教程仅提供一般处理程序即可实现,调用方式参考

http://URL路径:端口号/文件路径/文件名称.ashx?action=参数1&token=参数2

常见的接口内容

1)登录身份验证(合法、不合法)返回一些有用的参数

2)合法的身份下的设备列表及设备状态(激活的设备列表)

3)设备是否有效或是否激活

4)设备激活(拟计划扫二维码的形式进行激活 ajax进行交互提醒,设备只能激活一次)

5)扩展:修改服务端设备信息(名称等)、充值(可以使用一些扩展业务:邮件通知,语音电话通知,个性定制的内容等)

6)计划扩展:直接对设备进行高级配置(后续完善,对设备进行写操作,通过web界面对设备参数配置并写入或通过桌面winform管理软件进行配置)

调试工具可以用浏览器或postman进行调试
image.png
image.png
image.png
C# 物联网开发API接口系列(二)

【提纲】

1、如何写验证登录(参数:账号,密码)

2、switch方法的使用

3、json格式的使用方法,一些函数的使用注意事项
[C#] 纯文本查看 复制代码
<%@ WebHandler Language="C#" Class="check" %>
/*******************************************
 * 功能:管理客户端验证其登录合法性 2020.8.13
 * 参数:
 * action[必须]关键词决定查询类型
 * 根据自定义方法 传递参数 查询结果反馈打印
 * 举例 iot.jiuai.ltd?action=check&token=身份证&其他参数体
*******************************************/
using System;
using System.Text;
using System.Web;
using System.Data;
using System.Web.Services; //WebMethod 依赖于此引用
using DatabaseHelper; //数据库 增删改查 的方法 配置等
using System.Data.SqlClient; //sql命名空间
using md5Helper; //md5加密 验证密码时可用到


第一行:声明语言及类的名称(文件名称)

第二步:引用命名空间(需要多少引用多少,且第三方的要应用组件或部件)或自写的方法类等

调用接口的方法:url 方式之 get的方法

[C#] 纯文本查看 复制代码
public class check : IHttpHandler 
{
      //一些公共的变量或必须的参数 在此类最上层申请,多个方法可以共享调用
}

public void ProcessRequest (HttpContext context) 
{
     //所有参数处理入口函数(如果多个方法 通过不同的参数进行 分支处理)
    //此处用的是 switch 语句;下面举例说明
}

public void ProcessRequest (HttpContext context) 
    {
        context.Response.ContentType = "text/plain";//参数类型
        //必须参数 在类的顶层申请变量
        act = context.Request["action"];	//【必须】 参数名称可以自己定义
        token = context.Request["token"];//【必须】访问时携带,登录时查询更新      
        string regpacket="";                      //注册包(设备标识码)
        try
        {
            //********连接数据库***************
            if (!SqlHelper.isConnected)
                SqlHelper.check_SqlConn();           
            //**********************************  
            //本教程 对数据库进行操作 所以必须连接数据库(自定义类方法)
          
            //针对不同类型机型不同分支处理使用switch语句
            switch (act)
            {//目的分类型查询,名称自定义(这里分支名称参数和方法名称一致便于查询调用)
                case "login"://通过账号密码获取身份证token
                    string uc = context.Request["uc"];               //此方法需要2个参数 账号和密码
                    string pwd = context.Request["upwd"];      //密码
                    context.Response.Write(login(uc,pwd));//查询并返回结果json格式
                    break;
                case "getDevList"://获取该token下拥有的设备列表
                    uid = getUidbyToken(token);
                    context.Response.Write(getDevList(token));
                    break;
                case "getUserInfo"://通过token获取身份信息
                    uid=getUidbyToken(token);
                    context.Response.Write(ujson);
                    break;
                case "checkDevValidity"://检查设备是否有效
                    uid = getUidbyToken(token);
                    regpacket = context.Request["regpacket"];
                    context.Response.Write(checkDevValidity(regpacket));
                    break;
                case "actionBox"://激活设备(针对未激活的设备)
                    uid = getUidbyToken(token);
                    regpacket = context.Request["regpacket"];
                    context.Response.Write(actionBox(regpacket));//针对超级管理员可以做各种设备激活
                    break;
                default://所有未定义的方法,一律返回当前时间
                    context.Response.Write(DateTime.Now);
                    break;
            }
        }
        catch (Exception ex)
        {//返回异常/错误描述
            context.Response.Write("Error:" + ex.Message.ToString());
        }        
    }



登录验证 (有些解释文字就不写了看代码)


[C#] 纯文本查看 复制代码
/// <summary>
    /// 获取用户token,通过账号密码
    /// </summary>
    /// <param name="uc">账号或手机号</param>
    /// <param name="pwd">密码(未加密,明文)</param>
    /// <returns></returns>
    private string login(string uc, string pwd)
    {
        StringBuilder sb = new StringBuilder();//字符串拼接用到
        string result = "";
        
        if (SqlHelper.isConnected)
        {//数据库已连接
            try
            {
                SqlConnection SqlConn = new SqlConnection(SqlHelper.ConnString);
                if (SqlConn.State != ConnectionState.Connecting)
                {
                    SqlConn.Open();// 打开数据库连接
                }
                //修改加密方法  根据自己需要 可以加密后与数据库进行对比
                SqlCommand sqlCmd = new SqlCommand("SELECT top 1 uid,fuid,uCount,uToken,uTel,uName,uPwd FROM user_List WHERE (uTel='" + uc + "' OR uCount='" + uc + "') AND uPwd='" + md5Helper.MD5Util.MD5Hash(pwd,32,true) + "' AND uStatus=1", SqlConn);
                SqlDataReader rd = sqlCmd.ExecuteReader();//返回记录集
                if (rd.HasRows)//HasRows判断reader中是否有数据 
                {
                    if (rd.Read())
                    {//读取1条数据,如果多条时 用while进行操作
                        uid = Convert.ToInt16(rd["uid"]);    //返回用户id
                        fuid = Convert.ToInt16(rd["fuid"]);  //模块父id (可无限分级)顶级为0,子级时为uid
                        utoken = rd["uToken"].ToString();  //令牌(***)
                        utel = rd["uTel"].ToString();            //绑定的电话
                        uname = rd["uName"].ToString();  //设备昵称(暂不支持直接汉字,考虑编码方式)
                        //返回 用户信息(公共变量)
                        ujson = "{\"uid\":" + uid + ",\"fuid\":" + fuid + ",\"utoken\":\"" + utoken + "\",\"uname\":\"" + uname + "\",\"utel\":\"" + utel + "\"}";
                    }
                    //json标准格式除数字外,所有key和value必须有引号,此c#里用\"转移,注意{}的使用和逗号的处理!
                    //在这拼格式 非数据引用的{}不能出现Format里面否则无法识别;Format里只能数字对应的数据
                    result = string.Format("\"data\":\"{0}\",\"code\":{1},\"time\":\"{2}\"", utoken, 200, svrNowTime());//全部数据的最后一个逗号处理
                }
                else
                {//无结果时
                    result = string.Format("\"data\":\"{0}\",\"code\":{1},\"time\":\"{2}\"", "验证失败,请检查账号或密码!", 0, svrNowTime());
                }
                rd.Close();//统一释放资源
                rd = null;
                sqlCmd = null;
                SqlConn.Close();//关闭数据库连接   
                SqlConn = null;//否则不更新原内容
            }
            catch (Exception ex)
            {//错误时(字符串为空也必须加getNewString处理)
                result = string.Format("\"data\":\"[ERROR]:{0}\",\"code\":{1},\"time\":\"{2}\"", ex.Message.ToString(), -1, svrNowTime());
            }
        }
        return "{" + result + "}";//在此组合json格式;如果有全角的{} 时替换成半角的。最后处理!
    }

//code:为数字类型,data和time为字符串类型 注意加双引号
//***重点理解**** json中的{}和format中{0},{1}等参数的调用不能在一个字符串中一次成型
//json的开头{和结尾}  不要出现在 fromat中,在外面组合或全角的符号替代最后再替换掉!!



[C#] 纯文本查看 复制代码
/// <summary>
    /// 获取系统时间
    /// </summary>
    /// <returns></returns>
    private string svrNowTime()
    {
        return string.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now);
    }
    
    /// <summary>
    /// Json中不规则字符替换
    /// </summary>
    /// <param name="sstr"></param>
    /// <returns></returns>
    private string jsonReplace(string sstr)
    {
        return sstr.Replace("{", "{").Replace("}", "}");//前2个是中文的{}后面2个是英文的{},数据的最后个,的处理
    }


//通用方法(DELETE UPDATE)
       /// <summary>
        /// 执行SQL(执行UPDATE,DELETE,INSERT 操作)一条记录 ExecSqlHelper.execSQL
        /// </summary>
        /// <param name="exesql">sql语句</param>
        /// <returns></returns>
        public static string execSQL(string exesql)
        {
            //ConfigSQL();//配置连接参数
            //----------------------------------
            string execRet = "";
            SqlConnection SqlConn = new SqlConnection(SqlHelper.ConnString);
            try
            {
                if (SqlConn.State == ConnectionState.Closed)
                {
                    SqlConn.Open();
                }
                SqlCommand sqlCmd = new SqlCommand(exesql, SqlConn);
                int resultNum = sqlCmd.ExecuteNonQuery();//影响结果的行数
                if (resultNum > 0)
                {
                    execRet = "OK:" + resultNum;//成功
                }
                sqlCmd = null;
                SqlConn.Close();
                SqlConn.Dispose();
            }
            catch (Exception ex)
            {
                execRet = "SORRY:" + ex.Message.ToString();//失败
            }
            return execRet;
        }


//激活设备

/// <summary>
    /// 激活设备
    /// </summary>
    /// <param name="regpacket">注册包</param>
    /// <returns></returns>
    private string actionBox(string regpacket)
    {
        string exeResult = "";
        try
        {
            SqlConnection SqlConn = new SqlConnection(SqlHelper.ConnString);
            if (SqlConn.State != ConnectionState.Connecting) SqlConn.Open();            
            if (admintoken == token)
            {//是管理员(可以激活列黑的启用) 条件不同
                exeResult = ExecSqlHelper.execSQL("UPDATE box_List SET bActiveDate=GETDATE(),bStatus=1 WHERE bStatus!=1 AND bRegpacket='" + regpacket + "'");
            }else{//扫码激活
                exeResult = ExecSqlHelper.execSQL("UPDATE box_List SET bActiveDate=GETDATE(),bStatus=1 WHERE bStatus=0 AND bRegpacket='" + regpacket + "'");    
            }
            //通用方法返回值
            if (exeResult.IndexOf("OK") == 0)
            {
                exeResult = string.Format("\"data\":\"[OK]{0}\",\"code\":{1},\"time\":\"{2}\"","设备激活成功!", 200, DateTime.Now);
            }
            else
            {
                exeResult = string.Format("\"data\":\"{0}\",\"code\":{1},\"time\":\"{2}\"", "[SORRY]设备激活失败,请检查参数是否是否正确或已激活!", 0, DateTime.Now);
            }
        }
        catch (Exception ex)
        {
            exeResult = string.Format("\"data\":\"[ERROR]:{0}\",\"code\":{1},\"time\":\"{2}\"", ex.Message.ToString(), -1, DateTime.Now);
        }
        return "{" + exeResult + "}"; 
        
    }



[C#] 纯文本查看 复制代码
/// <summary>
    /// 获取设备列表
    /// </summary>
    /// <param name="_token">令牌</param>
    /// <returns></returns>
    private string getDevList(string _token)
    {
        string result = "";
        int listnum = 0;

        StringBuilder sb = new StringBuilder();
        try
        {
            if (SqlHelper.isConnected)
            {
                SqlConnection SqlConn = new SqlConnection(SqlHelper.ConnString);
                if (SqlConn.State != ConnectionState.Connecting)
                {
                    SqlConn.Open();// 打开数据库连接
                }
                //注意:参数是token查询用的是 uid 之前有一方法已经调用了 uid = getUidbyToken(token);
                SqlCommand sqlCmd = new SqlCommand("SELECT * FROM box_List WHERE bForUid=" + uid, SqlConn);
                SqlDataReader rd = sqlCmd.ExecuteReader();//返回的是记录集

                if (rd.HasRows)
                {
                    while (rd.Read())
                    {
                        listnum++;
                        sb.AppendFormat("{" + string.Format("\"regpacket\":\"{0}\",\"boxname\":\"{1}\",\"actived\":{2}", rd["bRegpacket"].ToString(), rd["bName"].ToString(),Convert.ToInt16(rd["bStatus"])) + "}");//可继续扩展其他属性
                        sb.AppendFormat(",");//最后一条需要处理此符号
                    }
                    sb.Remove(sb.ToString().LastIndexOf(','), 1);//处理最后一位符号(如何处理最后一个逗号)
                }                
                rd.Close();//统一释放资源
                rd = null;
                sqlCmd = null;
                SqlConn.Close();//关闭数据库连接   
                SqlConn = null;//否则不更新原内容 
            }
            //当data为数组时加[] 非数组及json格式写法
            if(listnum>0)
                result = string.Format("\"data\":[{0}],\"code\":{1},\"time\":\"{2}\"", sb.ToString().Replace("{", "{").Replace("}", "}"), 200, svrNowTime());
            else
                result = string.Format("\"data\":\"{0}\",\"code\":{1},\"time\":\"{2}\"", "请检查参数的合法性:" + _token, 0, svrNowTime());
            
        }
        catch (Exception ex)
        {
            result = string.Format("\"data\":\"[ERROR]:{0}\",\"code\":{1},\"time\":\"{2}\"", ex.Message.ToString(), -1, DateTime.Now);
        }

        return "{"+result+"}";//组合成标准的json格式的头尾
    }

    /// <summary>
    /// 验证智能模块的合法性
    /// </summary>
    /// <param name="reg">注册包</param>
    /// <returns></returns>
    private string checkDevValidity(string reg)
    {
        string _retu = "";
        try
        {
            SqlConnection SqlConn = new SqlConnection(SqlHelper.ConnString);
            if (SqlConn.State != ConnectionState.Connecting)
            {
                SqlConn.Open();// 打开数据库连接
            }
            //bStatus 1启用0禁用-1列黑
            SqlCommand sqlCmd = new SqlCommand("SELECT * FROM  box_List WHERE bStatus=1 AND bForUid=" + uid + " AND bRegpacket='" + reg + "'", SqlConn);
            SqlDataReader rd = sqlCmd.ExecuteReader();

            if (rd.HasRows)
            {
                rd.Read();
                _retu = string.Format("\"data\":\"[OK]{0}\",\"code\":{1},\"time\":\"{2}\"", rd["bRegpacket"], 200, DateTime.Now);
            }
            else
            {
                _retu = string.Format("\"data\":\"[SORRY]{0}\",\"code\":{1},\"time\":\"{2}\"", "验证失败,请检查参数是否正确!", 0, DateTime.Now);
            }
        }
        catch (Exception ex)
        {
            _retu = string.Format("\"data\":\"[ERROR]:{0}\",\"code\":{1},\"time\":\"{2}\"", ex.Message.ToString(), -1, DateTime.Now);
        }
        return "{" + _retu + "}"; //重新组合标准json格式头尾{}
        
    } 



    //通过token获取uid
    private int getUidbyToken(string tok)
    {
        int _uid;
        try
        {
            SqlConnection SqlConn = new SqlConnection(SqlHelper.ConnString);
            if (SqlConn.State != ConnectionState.Connecting)
            {
                SqlConn.Open();// 打开数据库连接
            }
            SqlCommand sqlCmd = new SqlCommand("SELECT top 1 uid,fuid,uToken,uTel,uName FROM user_List WHERE uToken='" + tok + "' AND uStatus=1", SqlConn);//uRole=8
            SqlDataReader rd = sqlCmd.ExecuteReader();//返回的是记录集   AND uStatus=1
            if (rd.HasRows)
            {
                if (rd.Read())
                {
                    uid = Convert.ToInt16(rd["uid"]);//***主要查询这个
                    fuid = Convert.ToInt16(rd["fuid"]);
                    utoken = rd["uToken"].ToString();
                    utel = rd["uTel"].ToString();
                    uname = rd["uName"].ToString();
                    //
                    ujson = "{\"uid\":" + uid + ",\"fuid\":" + fuid + ",\"utoken\":\"" + utoken + "\",\"uname\":\"" + uname + "\",\"utel\":\"" + utel + "\"}";
                }
                _uid = uid;//返回这个
            }
            else
            {
                _uid = -1;//没找到
            }
        }
        catch (Exception ex)
        {
            _uid = 0;//错误异常时0
        }
        return _uid;
    }








合法验证通过返回[OK]注册包格式 条件注册包


获取设备列表(条件:令牌)


成功获取令牌


获取令牌失败


到此为止,主要接口及方法已经讲解一遍!举一反三,触类旁通,学会学习 就很快了!
下一步,将接口部署到服务器下,进行访问即可!在管理客户端调用接口,根据返回json数据进行解析(了解json前端知识ajax)进行各种操作即可!有机会时间 会继续分享如何前端验证(ajax)解析数据并展现到页面上(H5) image.png image.png 实现的功能一览表 image.png 此登录暂未使用接口,模拟的自动登录 image.png 设备接线调试方法

免费评分

参与人数 3热心值 +3 收起 理由
攻城小怪兽 + 1 用心讨论,共获提升!
涛行 + 1 谢谢@Thanks!
老狗丶 + 1 谢谢@Thanks!麻烦给个连接原文

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

田田爱崽崽 发表于 2020-8-14 10:15
你能直接告诉我你从哪搬运来的嘛?我觉得去直接看原版可能好一些
 楼主| X5ZJ 发表于 2020-8-14 10:28
有些截图是边写边截图的,故有些图片是复制过来的。保证每一个字都是自己打出来的!昨晚连续更新4篇文字,2个平台同步更新的,昨晚发布于TT,次发于CSDN。今天更新于次!不喜勿喷,违规删!感谢您的理解。
编辑一篇文字也不容易。一个平台截图一遍不现实呢。部分图片复用的哦。保证是本人的原创!一些非必要的图片均已省略!
考虑到版规,不能发外部链接,所以 部分代码复制时难免会乱!深表歉意,代码部分我重新粘贴整理了。
省略一些文字。
关于服务端部署的看TT里一篇i6860470660372791816可以参考下。谢谢
头像被屏蔽
小非凡 发表于 2020-8-14 10:13
老狗丶 发表于 2020-8-14 10:16
麻烦老哥给个搬运连接,这排版没法看
老狗丶 发表于 2020-8-14 10:18
田田爱崽崽 发表于 2020-8-14 10:15
你能直接告诉我你从哪搬运来的嘛?我觉得去直接看原版可能好一些

https://blog.csdn.net/uaime/article/details/107991935
田田爱崽崽 发表于 2020-8-14 10:19
老狗丶 发表于 2020-8-14 10:18
https://blog.csdn.net/uaime/article/details/107991935

感谢老哥
bachelor66 发表于 2020-8-14 10:22
这排版无敌了                        
 楼主| X5ZJ 发表于 2020-8-14 10:34
老狗丶 发表于 2020-8-14 10:16
麻烦老哥给个搬运连接,这排版没法看

我的首发在TT(CSDN同步4篇),连续更新了5篇,部分图片没法重复截取只能复用。代码重新整理了。
 楼主| X5ZJ 发表于 2020-8-14 10:36

论坛的浏览器用起来非常不爽,刚才发一篇花费了20多分钟还乱糟糟 准备删除重发,后来没法删除重新编辑了一下,代码重新用本论坛的插入代码方法。
由于图片较多,边写边截图,部分图片 没法重新截取只能复用!如果需要可以私信交流,谢谢
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 01:48

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表