فهرست منبع

修改跳转逻辑使生效

zii 1 ماه پیش
والد
کامیت
04392fa3a0
9فایلهای تغییر یافته به همراه194 افزوده شده و 75 حذف شده
  1. 2 1
      .gitignore
  2. 1 0
      data_init.py
  3. 60 0
      job.md
  4. 10 8
      src/api/ability.rs
  5. 5 0
      src/api/area.rs
  6. 22 6
      src/api/auth.rs
  7. 75 42
      src/api/device.rs
  8. 17 17
      src/api/flow_task.rs
  9. 2 1
      src/main.rs

+ 2 - 1
.gitignore

@@ -1,4 +1,5 @@
 /target
 *.sqlite
 *.db
-*.json
+*.json
+bugs/

+ 1 - 0
data_init.py

@@ -12,6 +12,7 @@ id integer PRIMARY KEY,
 uname text not null,
 passwd text not null,
 nickname text not null,
+mqid text not null,
 headimgurl text not null default '',
 openid text not null,
 sex Integer not null default 0,

+ 60 - 0
job.md

@@ -26,3 +26,63 @@ mosquitto插件开发完了,地址在这里https://code.worldflying.cn/jevian/
 deadline是允许使用的最后时间(linux时间戳),当超过这个时间后,这条记录也就无效了。
 至于你是想设最后时效,还是享设只使用一次,亦或是同时有效,这个随你。功能完成了,你怎么用随便你。反正就是要注意一下,不要让一个账号被破解后,他可以操作我们的所有设备,这是绝对不被允许的。
 ```
+
+```txt
+一、用户登录
+mqtt服务器地址为plcmq.worldflying.cn
+端口为9001
+目前两个账号可用
+一个是:
+clientid:mqtt_client
+username:client
+password:123456
+另一个是:
+client:mqtt_client2
+username:client2
+password:123456
+必须通过加密的websocket去连接,也就是wss
+
+二、设备
+目前有两个设备,分别为460089721505216挂在mqtt_client下与460089721505219挂在mqtt_client2。
+
+三、调用
+以mqtt_client控制460089721505216为例
+客户端需要订阅如下topic
+/wf/Iot/client/460089721505216 用来获取烧录plc代码成功与失败状态
+460089721505216/dev/avty 用来获取设备在线状态,会收到ONLINE与OFFLINE
+460089721505216/DI0/state 用来获取DI0状态,会收到ON与OFF
+460089721505216/DI1/state 用来获取DI1状态,会收到ON与OFF
+460089721505216/DI2/state 用来获取DI2状态,会收到ON与OFF
+460089721505216/DI3/state 用来获取DI3状态,会收到ON与OFF
+460089721505216/DI4/state 用来获取DI4状态,会收到ON与OFF
+460089721505216/DI5/state 用来获取DI5状态,会收到ON与OFF
+460089721505216/DI6/state 用来获取DI6状态,会收到ON与OFF
+460089721505216/DI7/state 用来获取DI7状态,会收到ON与OFF
+460089721505216/DO0/state 用来获取DO0状态,会收到ON与OFF
+460089721505216/DO1/state 用来获取DO1状态,会收到ON与OFF
+460089721505216/DO2/state 用来获取DO2状态,会收到ON与OFF
+460089721505216/DO3/state 用来获取DO3状态,会收到ON与OFF
+460089721505216/DO4/state 用来获取DO4状态,会收到ON与OFF
+460089721505216/DO5/state 用来获取DO5状态,会收到ON与OFF
+460089721505216/DO6/state 用来获取DO6状态,会收到ON与OFF
+460089721505216/DO7/state 用来获取DO7状态,会收到ON与OFF
+460089721505216/BEEP/state 用来获取蜂鸣器状态,会收到ON与OFF
+客户端需要向如下topic发送消息
+/wf/Iot/device/460089721505216 用来发送烧录plc指令给设备
+460089721505216/DO0/cmd 用来控制DO0状态,可发送ON与OFF
+460089721505216/DO1/cmd 用来控制DO1状态,可发送ON与OFF
+460089721505216/DO2/cmd 用来控制DO2状态,可发送ON与OFF
+460089721505216/DO3/cmd 用来控制DO3状态,可发送ON与OFF
+460089721505216/DO4/cmd 用来控制DO4状态,可发送ON与OFF
+460089721505216/DO5/cmd 用来控制DO5状态,可发送ON与OFF
+460089721505216/DO6/cmd 用来控制DO6状态,可发送ON与OFF
+460089721505216/DO7/cmd 用来控制DO7状态,可发送ON与OFF
+460089721505216/BEEP/cmd 用来控制蜂鸣器状态,可发送ON与OFF
+
+四、烧录
+还是以mqtt_client控制460089721505216为例
+向topic /wf/Iot/device/460089721505216发送
+act=isp&imgurl=http://124.222.106.170/test_app_l011_nothing.bin
+其中imgurl后面跟的是固件的下载地址,我们的编译平台给你什么你填什么即可。
+如果烧录成功,topic /wf/Iot/client/460089721505216会收到success,失败会收到failure
+```

+ 10 - 8
src/api/ability.rs

@@ -90,7 +90,7 @@ pub async fn get_mqtt(
     };
     match state.db_lite.query_rows("select d.sn from device d left join map_user_device m on d.id=m.did where m.uid=?", [uid], |r|{r.get::<usize,String>(0)}).await{
         Ok(r)=>{
-            log(Debug, format!("get mqtt sub list{:?}",r));
+            // log(Debug, format!("get mqtt sub list{:?}",r));
             let mut fsub = if let Ok(f)=tokio::fs::File::create(format!("/var/lib/mosquitto/sub/{}",mqid)).await{f}else{
                 log(Warning, format!("fail at mqtt sub create"));
                 return Json(MqttBack{errcode: 3000, errmsg: Some("mqtt鉴权失败: 创建用户文件失败".to_string()),mqttp:None,clientid:None,mqttu:None});
@@ -100,24 +100,26 @@ pub async fn get_mqtt(
                 return Json(MqttBack{errcode: 3000, errmsg: Some("mqtt鉴权失败: 创建用户文件失败".to_string()),mqttp:None,clientid:None,mqttu:None});
             };
             if !r.is_empty(){
-                if let Err(e)=fpub.write(format!("/wf/Iot/device/{}", r.join("\n/wf/Iot/device/")).as_bytes()).await{
-                    log(Warning, format!("fail to write pub lit to file {e}"));
+                if let Err(e)=fpub.write(format!("/wf/Iot/device/{}\n{}", r.join("\n/wf/Iot/device/"),r.join("\n")).as_bytes()).await{
+                // if let Err(e)=fpub.write(format!("/wf/Iot/device/{}\n{}/+/cmd", r.join("\n/wf/Iot/device/"),r.join("/+/cmd\n")).as_bytes()).await{
+                    log(Warning, format!("fail to write pub list to file {e}"));
                 };
-                if let Err(e)=fsub.write(format!("/wf/Iot/client/{}", r.join("\n/wf/Iot/client/")).as_bytes()).await{
-                    log(Warning, format!("fail to write sub lit to file {e}"));
+                if let Err(e)=fsub.write(format!("/wf/Iot/client/{}\n{}", r.join("\n/wf/Iot/client/"),r.join("\n")).as_bytes()).await{
+                // if let Err(e)=fsub.write(format!("/wf/Iot/client/{}\n{}/+/state", r.join("\n/wf/Iot/client/"),r.join("/+/state\n")).as_bytes()).await{
+                    log(Warning, format!("fail to write sub list to file {e}"));
                 };
             } else {
                 if let Err(e)=fpub.write(String::new().as_bytes()).await{
-                    log(Warning, format!("fail to write pub lit to file {e}"));
+                    log(Warning, format!("fail to write pub list to file {e}"));
                 };
                 if let Err(e)=fsub.write(String::new().as_bytes()).await{
-                    log(Warning, format!("fail to write sub lit to file {e}"));
+                    log(Warning, format!("fail to write sub list to file {e}"));
                 };
             }
         }
         Err(e) => {
             if !e.is_empty(){
-            return Json(MqttBack{errcode: 3000, errmsg: Some("mqtt鉴权失败: 获取用户下属清单失败".to_string()),mqttp:None,clientid:None,mqttu:None});
+                return Json(MqttBack{errcode: 3000, errmsg: Some("mqtt鉴权失败: 获取用户下属清单失败".to_string()),mqttp:None,clientid:None,mqttu:None});
             }
         }
     }

+ 5 - 0
src/api/area.rs

@@ -130,6 +130,11 @@ pub async fn a_del(
             return token_fail();
         }
     };
+    if let Ok(n) = state.db_lite.query("select count(*) from map_user_device where did=?", [a.id], |r|{r.get::<usize,i64>(0)}).await{
+        if n > 0{
+            return Json(JsonBack{errcode: 3000, errmsg: Some(format!("该设备被分享, 请先取消分享"))});
+        }
+    }
     if let Err(e) = state.db_lite.query(
         "select a.id from map_user_area a where a.uid=? and a.aid=?", 
         (uid,a.id), 

+ 22 - 6
src/api/auth.rs

@@ -107,10 +107,13 @@ pub async fn auth(
         if let Err(e) = state.db_lite.execute("update user set token=? where id=?", (token.clone(), id)).await{
             println!("{e}");
         };
-        if let Some(did)= q.state.strip_prefix("did="){
-            if let Err(e) = state.db_lite.execute("update device set belongto=? where sn=? and belongto=0", (id,did)).await{
+        // 已注册时绑定设备
+        if let Some(sn)= q.state.strip_prefix("did="){
+            log(Debuging, format!("got did:  {}",sn));
+            if let Err(e) = state.db_lite.execute("update device set belongto=? where sn=? and belongto=0", (id,sn)).await{
                 println!("{e}");
-            }else if let Some(did)=state.db_lite.last_insert_rowid().await.ok(){
+            }else if let Ok(did) = state.db_lite.query("select id from device where sn=?", [sn], |r|{r.get::<usize,i64>(0)}).await{
+            //  if let Some(did)=state.db_lite.last_insert_rowid().await.ok(){  // 错误位置:update不会给last_insert_rowid
                 if let Err(e) = state.db_lite.execute("insert into map_user_device (uid, did)values(?,?)", (id,did)).await{
                     println!("{e}");
                 }
@@ -134,7 +137,7 @@ pub async fn auth(
             return Redirect::to(format!("{}/null",crate::WEBP).as_str())}}{b} else {
             log(Info, "redirect 5".to_string());
                 return Redirect::to(format!("{}/null",crate::WEBP).as_str())};
-        if let Err(e) = state.db_lite.execute("insert into user (uname,nickname,passwd,headimgurl,openid,sex,token) values(?,?,?,?,?,?,?)", (b.nickname.clone(),b.nickname.clone(),"",b.headimgurl,b.openid,b.sex,token.clone())).await{
+        if let Err(e) = state.db_lite.execute("insert into user (uname,nickname,passwd,headimgurl,openid,sex,token,mqid) values(?,?,?,?,?,?,?,?)", (b.nickname.clone(),b.nickname.clone(),"",b.headimgurl,b.openid,b.sex,token.clone(),format!("webu{}",super::token(5)))).await{
             println!("{e}");
         } 
         let uid = match state.db_lite.last_insert_rowid().await{
@@ -157,12 +160,25 @@ pub async fn auth(
             "insert into area (name,sup,createby)values('客厅',?,?)", 
             [area_sup,uid]
         ).await{println!("{e}")};
+        // 未注册时绑定设备
+        if let Some(sn)= q.state.strip_prefix("did="){
+            log(Debuging, format!("got did:  {}",sn));
+            if let Err(e) = state.db_lite.execute("update device set belongto=? where sn=? and belongto=0", (uid,sn)).await{
+                println!("{e}");
+            }else if let Ok(did) = state.db_lite.query("select id from device where sn=?", [sn], |r|{r.get::<usize,i64>(0)}).await{
+            //  if let Some(did)=state.db_lite.last_insert_rowid().await.ok(){  // 错误位置:update不会给last_insert_rowid
+                if let Err(e) = state.db_lite.execute("insert into map_user_device (uid, did)values(?,?)", (uid,did)).await{
+                    println!("{e}");
+                }
+            };  
+        }
         log(Debug, "register success".to_string());
         // 注册成功 函数末尾发生跳转到主页
         // return Redirect::to(format!("http://124.222.106.170/plc_ctrl?token={}#{}",token.clone(),q.state).as_str());
     };
     // request::Request::get("body");
     // log(Info, format!("bad happend {:?}",res));
-    log(Debug, format!("redirect back with token"));
-    return Redirect::to(format!("{}?token={}",crate::WEBP,token.clone()).as_str());
+    log(Debug, format!("redirect back with token, state: {}",q.state));
+    return Redirect::to(format!("{}?token={}{}",crate::WEBP,token.clone(),if q.state.starts_with("?"){format!("#{}",q.state)}else{"".to_string()}).as_str());
+    // return Redirect::to(format!("{}?token={}",crate::WEBP,token.clone()).as_str());
 }

+ 75 - 42
src/api/device.rs

@@ -82,6 +82,35 @@ pub async fn d_edit(
     errcode0()
 }
 
+#[derive(Deserialize)]
+pub struct Dshare{ 
+    token: String,
+    id: u64,
+    // ids: Vec<u64>,
+}
+
+pub async fn d_cancel_share(
+    State(state): State<AppState>,
+    Json(d): axum::extract::Json<Dshare>
+) -> Json<JsonBack> {
+    let uid=match check_token(&state, d.token).await {
+        Ok(id) => {id},
+        Err(_) => {
+            return token_fail();
+        }
+    };
+    if let Ok(n) = state.db_lite.execute(
+        "delete from map_user_device where did in (select id from device where belongto=?) and did=?",
+        [uid,d.id]).await {
+            if n ==0 {
+                return Json(JsonBack{errcode: 3000, errmsg: Some(format!("取消分享失败: 该设备不属于当前用户"))});
+            }
+    }else {
+        return Json(JsonBack{errcode: 3000, errmsg: Some(format!("删除用户设备关系失败"))});
+    }
+
+    errcode0()
+}
 
 pub async fn d_remove(
     State(state): State<AppState>,
@@ -108,20 +137,24 @@ pub async fn d_remove(
 }
 pub async fn d_del(
     State(state): State<AppState>,
-    Json(u): axum::extract::Json<Dedit>
+    Json(d): axum::extract::Json<Dedit>
 ) -> Json<JsonBack> {
-    let uid=match check_token(&state, u.token).await {
+    let uid=match check_token(&state, d.token).await {
         Ok(id) => {id},
         Err(_) => {
             return token_fail();
         }
     };
     if let Err(e) = state.db_lite.execute(
-        "update device set isdelete=1 where id=?",
-        [uid]).await {
+        "update device set belongto=0 where belongto=? and id=?",
+        [uid,d.id]).await {
+        return Json(JsonBack{errcode: 3000, errmsg: Some(format!("删除设备失败: {e}"))});
+    }
+    if let Err(e) = state.db_lite.execute(
+        "delete from map_user_device where did=? and uid=?",
+        [d.id,uid]).await {
         return Json(JsonBack{errcode: 3000, errmsg: Some(format!("删除设备失败: {e}"))});
     }
-
     errcode0()
 }
 #[derive(Deserialize)]
@@ -177,44 +210,44 @@ pub struct UTokenBack{
     pub area: Option<Vec<Area>>
 }
 
-#[derive(serde::Deserialize)]
-pub struct DNew{
-    token: String,
-    name: String,
-    area: u64,
-    belongto: u64,
-    r#type: String,
-}
+// #[derive(serde::Deserialize)]
+// pub struct DNew{
+//     token: String,
+//     name: String,
+//     area: u64,
+//     belongto: u64,
+//     r#type: String,
+// }
 
-// 添加设备的接口
-pub async fn d_new(
-    State(state): State<AppState>,
-    Json(u): axum::extract::Json<DNew>
-) -> Json<JsonBack> {
-     if let Ok( id) = check_token(&state, u.token).await {
-        id
-    } else {
-        return token_fail();
-    };
-    if let Err(e) = state.db_lite.execute(
-        "insert into device(name,area,belongto,typo)values(?,?,?,?)",
-        (u.name, u.area, u.belongto,u.r#type)).await {
-        return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加设备失败: {e}"))});
-    }
-    match state.db_lite.execute(format!("insert into map_user_device (did,uid)values(?,?)").as_str(), 
-    (
-        match state.db_lite.last_insert_rowid().await{
-            Ok(id) => id,
-            Err(_) => 0,
-        }
-        , u.belongto)).await{
-        Ok(_) => {},
-        Err(e) => {
-            return Json(JsonBack{errcode: 3000, errmsg: Some(format!("更新失败{e}"))});
-        }
-    }
-    errcode0()
-}
+// // 添加设备的接口
+// pub async fn d_new(
+//     State(state): State<AppState>,
+//     Json(u): axum::extract::Json<DNew>
+// ) -> Json<JsonBack> {
+//      if let Ok( id) = check_token(&state, u.token).await {
+//         id
+//     } else {
+//         return token_fail();
+//     };
+//     if let Err(e) = state.db_lite.execute(
+//         "insert into device(name,area,belongto,typo)values(?,?,?,?)",
+//         (u.name, u.area, u.belongto,u.r#type)).await {
+//         return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加设备失败: {e}"))});
+//     }
+//     match state.db_lite.execute(format!("insert into map_user_device (did,uid)values(?,?)").as_str(), 
+//     (
+//         match state.db_lite.last_insert_rowid().await{
+//             Ok(id) => id,
+//             Err(_) => 0,
+//         }
+//         , u.belongto)).await{
+//         Ok(_) => {},
+//         Err(e) => {
+//             return Json(JsonBack{errcode: 3000, errmsg: Some(format!("更新失败{e}"))});
+//         }
+//     }
+//     errcode0()
+// }
 
 pub async fn d_all(
     State(state): State<AppState>,

+ 17 - 17
src/api/flow_task.rs

@@ -81,12 +81,12 @@ pub async fn checkout_flow_task_of_share_device(
     Json(u): Json<CheckoutShare>
 ) -> Json<JsonBack> {
     let uid = match check_token(&state, u.token).await {
-        Ok(id) => id,
+        Ok(uid) => uid,
         Err(_) => {
             return token_fail();
         }
     };
-    let (id, typo,interval, createby) = match state.db_lite.query(
+    let (the_id, typo,interval, createby) = match state.db_lite.query(
         "select did,typo,strftime('%s','now')-strftime('%s',createtime),createby from flow_task_share where ticket=? and isdelete=0",
         [
             // params.linkrand.clone()
@@ -104,54 +104,54 @@ pub async fn checkout_flow_task_of_share_device(
             // "update flow_task_share set isdelete=1 where ticket=?", 
             [u.linkrand.clone()]).await{
             Ok(_) => {},
-            Err(e) => return Json(JsonBack{errcode: 3001, errmsg: Some(format!("删除分享流程失败: {e}"))}),
+            Err(e) => return Json(JsonBack{errcode: 3000, errmsg: Some(format!("删除分享流程失败: {e}"))}),
         };
-        return Json(JsonBack{errcode: 3001, errmsg: Some("分享流程已过期".to_string())});
+        return Json(JsonBack{errcode: 3000, errmsg: Some("分享流程已过期".to_string())});
     }
     // 为2时转让设备,需要移除原用户与设备的关系
     if typo == 2{
-        if let Err(e) = state.db_lite.execute("delete from map_user_device where uid=? and did=?", (createby, id)).await{
-            return Json(JsonBack{errcode: 3001, errmsg: Some(format!("转让时删除设备关系失败: {e}"))});
+        if let Err(e) = state.db_lite.execute("delete from map_user_device where uid=? and did=?", (createby, the_id)).await{
+            return Json(JsonBack{errcode: 3000, errmsg: Some(format!("转让时删除设备关系失败: {e}"))});
         }
     }
 
     // 为0时分享区域
     if typo == 0{
-        match state.db_lite.execute("insert into map_user_area(uid,aid)values(?,?)", [uid, id]).await{
+        match state.db_lite.execute("insert into map_user_area(uid,aid)values(?,?)", [uid, the_id]).await{
             Ok(i) => {
                 log(Debug, format!("影响一级区域数量{i}个"));
             },
-            Err(e) => if e==""{/*Unique异常跳过 */} else {return Json(JsonBack{errcode: 3002, errmsg: Some(format!("添加区域分享关系失败: {e}"))});},
+            Err(e) => if e==""{/*Unique异常跳过 */} else {return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加区域分享关系失败: {e}"))});},
         };
-        match state.db_lite.execute("insert into map_user_area(uid,aid) select ?,id from area where sup=? and id not in (select aid from map_user_area where uid=?)", [uid, id,uid]).await{
+        match state.db_lite.execute("insert into map_user_area(uid,aid) select ?,id from area where sup=? and id not in (select aid from map_user_area where uid=?)", [uid, the_id,uid]).await{
             Ok(i) => {
                 log(Debug, format!("影响二级区域数量{i}个"));
             },
-            Err(e) =>  if e==""{/*Unique异常跳过 */} else {return Json(JsonBack{errcode: 3002, errmsg: Some(format!("添加区域下级分享关系失败: {e}"))})},
+            Err(e) =>  if e==""{/*Unique异常跳过 */} else {return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加区域下级分享关系失败: {e}"))})},
         };
-        match state.db_lite.execute("insert into map_user_device(uid,did) select ?,device.id from device where area in (select id from area where area.sup=?) and device.id not in (select did from map_user_device where uid=?)", [uid, id,uid]).await{
+        match state.db_lite.execute("insert into map_user_device(uid,did) select ?,device.id from device where area in (select id from area where area.sup=?) and device.id not in (select did from map_user_device where uid=?)", [uid, the_id,uid]).await{
             Ok(i) => {
                 log(Debug, format!("影响设备数量{i}个"));
             },
-            Err(e) =>if e==""{/*Unique异常跳过 */} else { return Json(JsonBack{errcode: 3002, errmsg: Some(format!("添加区域下全部设备关系失败: {e}"))})},
+            Err(e) =>if e==""{/*Unique异常跳过 */} else { return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加区域下全部设备关系失败: {e}"))})},
         };
 
     }
     // 为1时分享设备,为2时转让设备,此处添加设备与新用户的关系
     else if typo == 1 || typo == 2 {
-        match state.db_lite.execute("insert into map_user_device(uid,did)values(?,?)", [uid, id]).await{
+        match state.db_lite.execute("insert into map_user_device(uid,did)values(?,?)", [uid, the_id]).await{
             Ok(_) => {},
-            Err(e) => if e==""{/*Unique异常跳过*/}else{ return Json(JsonBack{errcode: 3002, errmsg: Some(format!("添加设备分享关系失败: {e}"))});}
+            Err(e) => if e==""{/*Unique异常跳过*/}else{ return Json(JsonBack{errcode: 3000, errmsg: Some(format!("添加设备分享关系失败: {e}"))});}
         };    
     } else {
-        return Json(JsonBack{errcode: 3003, errmsg: Some("分享流程类型错误".to_string())});
+        return Json(JsonBack{errcode: 3000, errmsg: Some("分享流程类型错误".to_string())});
     }
 
     // 转让设备需要将belongto更新
     if typo == 2{
-        match state.db_lite.execute("update device set belongto=? where id=?", [uid, id]).await{
+        match state.db_lite.execute("update device set belongto=? where id=?", [uid, the_id]).await{
             Ok(_) => {},
-            Err(e) => return Json(JsonBack{errcode: 3004, errmsg: Some(format!("更新设备分享关系失败: {e}"))}),
+            Err(e) => return Json(JsonBack{errcode: 3000, errmsg: Some(format!("更新设备分享关系失败: {e}"))}),
         }
         match state.db_lite.execute("delete from flow_task_share where ticket=?", [u.linkrand.clone()]).await{
             Ok(_) => {},

+ 2 - 1
src/main.rs

@@ -140,8 +140,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
             
             .route("/device/edit", post(api::device::d_edit))
             // .route("/device/transform", post(api::device::d_transform))
-            .route("/device/new", post(api::device::d_new))
+            // .route("/device/new", post(api::device::d_new))
             .route("/device/delete", post(api::device::d_del))
+            .route("/device/unshare", post(api::device::d_cancel_share))
             .route("/device/remove", post(api::device::d_remove))
 
             .route("/device/burn", post(api::device::burn))