7962| 2
|
[项目] 如何制作Makerspace NFC组件管理系统 |
通过使用Particle Photon和终端数据库以及网页界面,并采用NFC贴纸对电子组件进行追踪。 此项目需要用到的工具材料: 硬件组件 RC522 NFC标记阅读器 OLED 2828 262K色 全彩显示模块 Adafruit电容式触摸传感器 - MPR121 软件应用程序和在线服务 Autodesk Fusion 360 粒子搭建Web IDE MySQL NodeJS 手动工具和制造设备 3D打印机 烙铁 故事: 目的 想象一下,作为创客空间的所有者,您可以自行组织和跟踪仓库内的设备。有时您的成员可能会借用这些组件但是并没有归还给您,或者他们将自己的工具材料带来后并将二者组装起来。这就是为什么我需要创建一个单独的库存管理系统,它使用NFC和仓储箱(bin)对具有物联网功能的组件进行组织和跟踪。 演示视频 总体布局 每个bin都会被分配一个名称、描述、一般类型,以及与其贴纸相对应的NFC UID。当零件进入bin时,每个零件都会有一个名称、描述、数量、类型,以及它所属bin的ID。所有这些数据都托管在MySQL数据库中。我使用NodeJS网络服务器创建了一个云API,然后可以对MySQL数据库执行某些操作,例如创建新组件或删除bin。在硬件方面,我使用带128x128 OLED屏幕和NFC读取器的Particle Photon,以及用于虚拟按钮的MPR121。 我还创建了一个网页,允许完全访问API,以便能够轻松、干净地更改几乎所有关于bin或组件的内容。 网络服务器 我决定使用最适合我的用例的Express库,因为它允许创建简单的RESTful API,并且路径创建也非常简单。我开始使用npm安装express,以及cors和mysql。然后我用“require('包名package_name ')”将它们放置在顶部全局定义程序里面。我使用MySQL库的createPool函数连接到MySQL数据库,因为它能够轻松安全地创建和释放连接。每个API路径都有自己的功能,其中“app.post”用于POST请求,“app.get”用于GET请求。 字符串是发送数据的路径,例如“/parts/get_all_bins”。函数内容各不相同,但通常每个函数都建立与数据库的连接,解析请求数据,并执行某项查询。在数据库和设备之间添加缓冲区会创建一层安全控制区。 MySQL数据库 那么虽然目前存在一种访问和更改数据的方法,但是数据究竟存储在何处或如何存储?当我安装MySQL数据库时,我还安装了MySQL Workbench,它允许用户对其数据库进行管理。我创建了名为“components”的新模式,并创建了两个表:parts和bin。 每张表都需要不同的列,因为bin没有具体数量,而且组件不需要NFC UID。 我还创建了需要登录密码的新用户,以便与NodeJS服务器同时使用。如果有人获得对服务器代码的访问权限,那么执行此操作而不是使用root密码会大大提高安全性。 NFC RFID标签 当我第一次开始这个项目时,我只有几张NFC卡,所以我必须找到一种新的数据存储和扫描方法。然后我去了AliExpress寻找更好的媒介。我看到了NFC贴纸,它贴有一个非常小的天线和芯片,但是整个纸张非常薄而且很小。这样我们就可以将它们粘在bin上并轻松读取。 硬件 那么bin究竟以何种方式进行扫描,数量如何变化?对于这个问题,我使用RC522 RFID阅读器读取NFC标签。为了显示数据和指令,我使用了一个使用SSD1351控制器的128x128 OLED屏幕。由于此项目适用于创客空间,我希望避免使用物理按钮,因为它们可能会出现磨损。MPR121电容式触控板价格低廉并且具有I2C接口,最终被我选用。 它最多可以处理12个不同的频道。在我的设计方案中,我增加3个附有1/4英寸铜带的地方。这些铜片在触摸时可以充当按钮。 硬件代码 由于系统需要通过一系列繁琐的步骤进行创建,因此我开发了一个系统,该系统使用状态机对显示的页面进行控制。它按照以下顺序依次排列:搜索选项卡->选择bin ->显示bin ->显示组件->更改数量。为了解析来自Web服务器的响应,我使用了SparkJson库。在每个阶段,请求会自动生成并将其发送到Web服务器。 网页 这是整个项目中最难更正的部分。它包含三个组件:HTML、JavaScript和CSS。 由于我还是CSS新手,我使用的是W3 School的W3.CSS课程。为了确保界面的简洁,我制作了一个简单的按钮网格,每个按钮对应一个弹出的模态卡。每张模态卡右上角都有一个关闭按钮。列表箱和列表项等按钮显示一个在单击时更新的列表中。添加新项目和添加bin等按钮都包含在一个表单内。 JavaScript代码过于复杂,无法在本文中进行解释,但是它基本上包含在提交表单时调用的各种函数中。某些函数还会填充选择元素和表。 用法 如需使用该系统,用户将首先通过输入其名称和其他数据来填充他们所拥有的bin列表。然后按照类似的方式创建组件。如有需要,通过一个按钮即可批量创建组件,例如塞满各种电阻值的bin。一旦所有事情准备就绪,那么现在就可以使用photon对bin进行扫描了。 未来计划 在未来,我希望扩展系统,使其包括登录和所有权方面的内容。用户可以扫描他们的makerspace RFID卡,然后访问他们自己的个人bin。 原理图 代码 物理ReaderC/C++ [mw_shl_code=applescript,true] // This #include statement was automatically added by the Particle IDE.#include <Adafruit_MPR121.h> // This #include statement was automatically added by the Particle IDE. #include <MFRC522.h> // This #include statement was automatically added by the Particle IDE. #include <SparkJson.h> #include "application.h" #include "HttpClient.h" #include "Particle.h" #define cs D4 #define sclk A3 #define mosi A5 #define rst D5 #define dc D6 #define SS_PIN A2 #define RST_PIN D2 #define LEFT 0 #define CENTER 2 #define RIGHT 4 // Color definitions #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF #include "Adafruit_mfGFX/Adafruit_mfGFX.h" #include "Adafruit_SSD1351_Photon.h" // Option 1: Hardware SPI - uses some analog pins, but much faster Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, rst); Adafruit_MPR121 cap = Adafruit_MPR121(); MFRC522 mfrc522(SS_PIN, RST_PIN); HttpClient http; http_header_t headers[] = { { "Content-Type", "application/json" }, {"Accept", "*/*"}, {NULL, NULL} }; http_request_t request; http_response_t response; uint16_t lasttouched = 0; uint16_t currtouched = 0; char char_buf[500]; enum States { SEARCH_FOR_CARD, SELECT_BIN, DISPLAY_BIN, DISPLAY_PART, CHANGE_QUANTITY }; struct card_uid{ int size; int id_digits[7]; String id_string; } current_card; int bin_id = 0, part_id = 0, part_qty = 0;; States state = SEARCH_FOR_CARD; void setup(void) { StaticJsonBuffer<400> jsonBuffer; Serial.begin(9600); Serial.print("hello!"); tft.begin(); reset_screen(); mfrc522.setSPIConfig(); mfrc522.PCD_Init(); // Init MFRC522 card cap.begin(0x5A); request.hostname = "IP address goes here"; request.port = 3010; } void loop() { switch(state){ case SEARCH_FOR_CARD: reset_screen(); Serial.println("Scan a MIFARE Classic card."); tft.setTextSize(2); tft.println("Waiting for card to be scanned"); current_card.id_string = ""; wait_for_card(); state = SELECT_BIN; break; case SELECT_BIN: select_bin(); break; case DISPLAY_BIN: part_id = display_parts(); //delay(1000); break; case DISPLAY_PART: display_part(part_id); //delay(1000); break; case CHANGE_QUANTITY: change_quantity(part_id); //delay(1000); break; } } void change_quantity(int item_id){ request.path = "/parts/change_amount"; reset_screen(); int amount = 0, quantity = part_qty; String inc_dec = ""; tft.setTextSize(1); tft.println("Change | New amount"); tft.setCursor(0,120); tft.println("Increase|Set|Decrease"); tft.setTextSize(3); while(1){ delay(200); Particle.process(); tft.fillRect(0,40,128,60,BLACK); tft.setCursor(20,45); tft.print(amount); tft.print(" | "); tft.print(quantity); while(1){ currtouched = cap.touched(); Particle.process(); if((currtouched & _BV(LEFT))){ amount++; quantity++; break; } else if((currtouched & _BV(CENTER))){ if(amount >= 0){ inc_dec = "true"; } else{ inc_dec = "false"; } request.body = "{\"id\":"+String(item_id)+",\"inc_dec\":"+inc_dec+",\"amount\":"+String(abs(amount))+"}"; http.post(request,response, headers); reset_screen(); tft.setTextSize(2); tft.println("Success!"); delay(2000); state = SEARCH_FOR_CARD; return; } else if((currtouched & _BV(RIGHT))){ if(quantity>0){ amount--; quantity--; break; } } } } } void display_part(int item_id){ reset_screen(); StaticJsonBuffer<500> jsonBuffer; request.path = "/parts/get_part_info"; request.body = "{\"id\":\""+String(item_id)+"\"}"; http.post(request,response, headers); response.body.toCharArray(char_buf,500); JsonObject& root = jsonBuffer.parseObject(char_buf); int id = root["id"]; const char* name = root["name"]; int quantity = root["quantity"]; const char* desc = root["description"]; tft.print("Name: "); tft.println(name);tft.println(); tft.print("Item id: "); tft.println(id);tft.println(); tft.print("Quantity: "); tft.println(quantity);tft.println(); tft.println("Description: ");tft.println(); tft.println(desc);tft.println(); print_divider(); tft.setCursor(0,120); tft.print("Back Select"); //delay(1000); while(1){ currtouched = cap.touched(); if((currtouched & _BV(LEFT))){ state = DISPLAY_BIN; return; } else if((currtouched & _BV(CENTER))){ state = CHANGE_QUANTITY; part_qty = quantity; return; } Particle.process(); } } int display_parts(){ int current_row = 0; static char new_char_buf[600]; StaticJsonBuffer<1000> jsonBuffer; request.path = "/parts/get_parts_from_bin"; request.body = "{\"bin_id\":\""+String(bin_id)+"\"}"; http.post(request,response, headers); response.body.toCharArray(new_char_buf,600); Serial.println(new_char_buf); JsonObject& root = jsonBuffer.parseObject(const_cast<char*> (response.body.c_str())); reset_screen(); if(!root.success()) Serial.println("couldnt parse"); int entries = root["entries"]; Serial.println(entries); while(1){ reset_screen(); Particle.process(); //Serial.println(entry_num); int entry_num = entries; for(int row=0;row<entry_num;row++){ int id = root["rows"][row]["id"]; const char* name = root["rows"][row]["name"]; Serial.println(name); if(current_row==row){ tft.print("> "); } tft.println(name); //print_divider(); } tft.setCursor(0,120); tft.print("Up Select Down"); while(1){ Particle.process(); currtouched = cap.touched(); if((currtouched & _BV(LEFT))){ if(current_row>0){ current_row--; break; } } else if((currtouched & _BV(RIGHT))){ if(current_row<entry_num-1){ current_row++; break; } } else if((currtouched & _BV(CENTER))){ int id = root["rows"][current_row]["id"]; state = DISPLAY_PART; return id; } } } } void select_bin(){ StaticJsonBuffer<300> jsonBuffer; request.path = "/parts/get_bin_info"; String rfid = current_card.id_string; request.body = "{\"rfid\":\""+rfid+"\"}"; tft.println(request.body); http.post(request,response, headers); tft.println(response.body); response.body.toCharArray(char_buf,500); JsonObject& root = jsonBuffer.parseObject(char_buf); reset_screen(); Serial.println(response.body); tft.print("Bin ID: "); int id = root["id"]; bin_id = id; tft.println(id); tft.print("Bin RFID: "); tft.println(rfid); tft.println("Bin description: "); const char* desc = root["description"]; tft.println(desc); print_divider(); tft.setCursor(0,100); tft.println("Use this bin?"); tft.println("Yes No"); int choice = 0; while(!choice){ currtouched = cap.touched(); Particle.process(); if((currtouched & _BV(LEFT))){ state = DISPLAY_BIN; return; } else if((currtouched & _BV(RIGHT))){ state = SEARCH_FOR_CARD; return; } lasttouched = currtouched; } } void testdrawtext(char *text, uint16_t color) { tft.setCursor(0,0); tft.setTextColor(color); tft.print(text); } void print_divider(){ tft.setTextSize(1); tft.println("----------"); } void reset_screen(){ tft.fillScreen(BLACK); tft.setCursor(0,0); tft.setTextColor(WHITE); tft.setTextSize(1); } void wait_for_card(){ while(1){ Particle.process(); if (mfrc522.PICC_IsNewCardPresent()) { reset_screen(); tft.setTextSize(2); tft.println("NFC tag found!"); while(1){ if (mfrc522.PICC_ReadCardSerial()) { Serial.print("Card UID:"); current_card.size = mfrc522.uid.size; for (byte i = 0; i < mfrc522.uid.size; i++) { Serial.print(mfrc522.uid.uidByte < 0x10 ? " 0" : " "); Serial.print(mfrc522.uid.uidByte, HEX); current_card.id_string += mfrc522.uid.uidByte < 0x10 ? " 0" : " "; current_card.id_string += String(mfrc522.uid.uidByte, HEX); current_card.id_digits = mfrc522.uid.uidByte; } current_card.id_string.trim(); Serial.println(); delay(1000); return; } } } } } String get_bin_info(String rfid){ request.path = "/parts/get_bin_info"; request.body = "{\"rfid\":\""+rfid+"\"}"; http.post(request,response, headers); //tft.print(response.body); //delay(2000); return String(response.body); } Node Js WebserverJavaScript const mysql = require('mysql'); var express = require('express'); var parser = require('body-parser'); const cors = require('cors'); var app = express(); app.use(parser.json({extended: true})); app.use(cors()); app.options('*',cors()); var con = mysql.createPool({ host: "127.0.0.1", user: "username", password: "password", database: "components" }); app.post("/parts/get_part_info", function(request, response){ console.log(request.body); con.getConnection(function(err,connection){ if(err) throw err; var query = `SELECT * FROM parts WHERE id = '${request.body.id}'`; connection.query(query,function(err, result){ connection.release(); if (err) throw err; console.log(result[0]); response.send(result[0]); }); }); }); app.post("/parts/get_parts_from_bin", function(request, response){ console.log(request.body); con.getConnection(function(err,connection){ if(err) throw err; var query = `SELECT id, name FROM parts WHERE belongs_to = '${request.body.bin_id}'`; if(request.body.detailed !== undefined){ query = `SELECT * FROM parts WHERE belongs_to = '${request.body.bin_id}'`; } connection.query(query,function(err, result){ connection.release(); if (err) throw err; res_json = {rows:result,entries:result.length}; console.log(res_json); response.send(res_json); }); }); }); app.post("/parts/get_bin_info", function(request, response){ console.log(request.body); con.getConnection(function(err,connection){ if(err) throw err; var query = `SELECT * FROM bins WHERE rfid = '${request.body.rfid}'`; console.log(query); connection.query(query,function(err, result){ connection.release(); if (err) throw err; console.log(result[0]); response.send(result[0]); }); }); }); app.get("/parts/get_bins", function(request, response){ con.getConnection(function(err,connection){ if(err) throw err; var query = "SELECT * FROM bins"; connection.query(query, function(err, result){ connection.release(); if(err) throw err; //var response_json = {entries_amount:result.length,rows:result} //console.log(result); response.send(result); }); }); }); app.get("/parts/get_parts", function(request, response){ con.getConnection(function(err,connection){ if(err) throw err; var query = "SELECT * FROM parts"; connection.query(query, function(err, result){ connection.release(); if(err) throw err; //var response_json = {entries_amount:result.length,rows:result} //console.log(result); response.send(result); }); }); }); app.post("/parts/add_part", function(request, response){ con.getConnection(function(err,connection){ //console.log(request.body); if(err) throw err; var body = request.body; var query = `INSERT INTO parts (name, value, quantity, description, package, \ belongs_to, is_SMD) VALUES ('${body.name}','${body.value}', \ '${body.quantity}','${body.description}','${body.package}','${body.belongs}', \ '${body.is_SMD}')`; connection.query(query, function(err, result){ connection.release(); if(err) throw err; }); //response.send_header('Access-Control-Allow-Origin', '*') response.send("ok"); }); }); app.post("/parts/add_bin", function(request, response){ con.getConnection(function(err,connection){ //console.log(request.body); if(err) throw err; var body = request.body; var query = `INSERT INTO bins (name, rfid, description, type, is_SMD, \ is_mixed) VALUES ('${body.name}','${body.rfid}', \ '${body.description}','${body.type}','${body.is_smd}','${body.is_mixed}')`; connection.query(query, function(err, result){ connection.release(); if(err) throw err; }); //response.send_header('Access-Control-Allow-Origin', '*') response.send("ok"); }); }); app.post("/parts/remove_bin", function(request, response){ con.getConnection(function(err,connection){ //console.log(request.body); if(err) throw err; var body = request.body; var query = `DELETE FROM bins WHERE (id = '${body.bin_id}')`; connection.query(query, function(err, result){ //connection.release(); if(err) throw err; }); var query = `DELETE FROM parts WHERE (belongs_to = '${body.bin_id}')`; connection.query(query, function(err, result){ connection.release(); if(err) throw err; }); //response.send_header('Access-Control-Allow-Origin', '*') response.send("ok"); }); }); app.post("/parts/remove_item", function(request, response){ con.getConnection(function(err,connection){ if(err) throw err; var body = request.body; var query = `DELETE FROM parts WHERE (id = '${body.item_id}')`; connection.query(query, function(err,result){ connection.release(); if(err) throw err; }); response.send("ok"); }); }); app.post("/parts/change_amount", function(request,response){ console.log(request.body); var amount = request.body.amount; var inc_dec = request.body.inc_dec; var item_id = request.body.id; if(inc_dec === true){ var query = `UPDATE parts SET quantity = quantity + ${amount} WHERE id = ${item_id} and quantity >= 0`; } else if(inc_dec === false){ var query = `UPDATE parts SET quantity = quantity - ${amount} WHERE id = ${item_id} and quantity >= 0+${amount}`; } console.log(query); con.getConnection(function(err,connection){ if(err) throw err; connection.query(query,function(err, result){ connection.release(); if (err) throw err; console.log(`Successfully changed ${result.changedRows} entries`); response.send(`Successfully changed ${result.changedRows} entries`); }); }); }); app.listen(3010); [/mw_shl_code] HTML网页 [mw_shl_code=applescript,true]<html> <head> <title>Part Tracker</title> <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> <script type="text/javascript" src="https://cdn.jsdelivr.net/particle-api-js/5/particle.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="part_tracker_script.js"></script> <link rel="stylesheet" href="part_tracker_styles.css"> </head> <body class="w3-content" style="width: 100%"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 50px; width: 100%;"> <h1>Part Tracker Main Page</h1> </header> <div id="action_container" class="w3-display-container w3-white" style="height:100%;"> <div id="actions" class="w3-display-top w3-center"> <div class="w3-row-padding" style="margin-bottom: 50px;"> <div class="w3-col s4 item" id="add_new_bulk_item"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('add_bulk_item').style.display='block';"> <p>Add new items in bulk</p> </button> </div> <div class="w3-col s4 item" id="list_bins"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('list_all_bins').style.display='block';refresh_selects();"> <p>List bins</p> </button> </div> <div class="w3-col s4 item" id="list_items"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('list_all_items').style.display='block';"> <p>List items</p> </button> </div> </div> <div class="w3-row-padding" style="margin-bottom: 50px;"> <div class="w3-col s4 item" id="add_new_item"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('add_one_item').style.display='block';"> <p>Add a new item</p> </button> </div> <div class="w3-col s4 item" id="remove_item_button"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('remove_item').style.display='block';"> <p>Remove item</p> </button> </div> <div class="w3-col s4 item" id="list_items_btn"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('list_items_from_bin').style.display='block';"> <p>List items in a bin</p> </button> </div> </div> <div class="w3-row-padding" style="margin-bottom: 50px;"> <div class="w3-col s4 item" id="change_qty_btn"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('change_qty').style.display='block';"> <p>Change item quantity</p> </button> </div> <div class="w3-col s4 item" id="add_bin_btn"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('add_bin').style.display='block';"> <p>Add bin</p> </button> </div> <div class="w3-col s4 item" id="remove_bin_btn"> <button class="modal_button w3-button w3-white w3-border w3-round" onclick="document.getElementById('remove_bin').style.display='block';"> <p>Remove bin</p> </button> </div> </div> <div class="w3-row-padding" style="margin-bottom: 25px;"> <div class="w3-col s4 item w3-center" id="refresh_bins"> <button class="w3-button w3-white w3-border w3-round"> <p>Refresh bins</p> </button> </div> </div> </div> </div> <div id="list_all_items" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 25px;"> <h2>View all parts</h2> </header> <div class="w3-container" style="margin: auto; width: 100%;"> <span class="w3-button w3-display-topright">×</span> <table class="w3-table-all w3-hoverable" id="all_part_table"> <tr class='w3-blue-gray'> <th>Name</th> <th>ID</th> <th>Value</th> <th>Quantity</th> <th>Description</th> <th>Package</th> <th>Bin ID</th> <th>Is SMD?</th> </tr> </table> </div> </div> </div> <div id="list_all_bins" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 25px;"> <h2>View all bins</h2> </header> <div class="w3-container" style="margin: auto; width: 100%;"> <span class="w3-button w3-display-topright">×</span> <table class="w3-table-all w3-hoverable" id="all_bin_table"> <tr class='w3-blue-gray'> <th>Name</th> <th>ID</th> <th>RFID UID</th> <th>Type</th> <th>Description</th> <th>Is SMD?</th> <th>Is mixed?</th> </tr> </table> </div> </div> </div> <div id="list_items_from_bin" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 25px;"> <h2>View parts from bin</h2> </header> <div class="w3-container" style="margin: auto; width: 100%;"> <span class="w3-button w3-display-topright">×</span> <select class="w3-select bin_select" name="bins" id="list_item_bin_select" style="margin-bottom: 25px;"> </select> <table class="w3-table-all w3-hoverable" id="item_from_bin_table" style="display: none; width: 100%; margin-bottom:40px;"> </table> <label style='display: none; margin-bottom: 28px; font-size: 40px;' class="w3-center" id="no_data_label">No data found!</label> </div> </div> </div> <div id="remove_item" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 25px;"> <h2>Remove an item</h2> </header> <div class="w3-container" style="margin: auto; width: 100%;"> <span class="w3-button w3-display-topright">×</span> <div class="w3-container" style="margin: auto; width: 100%;"> <form id="remove_item_form" class="w3-container" > <label>Select a bin:</label> <select class="w3-select bin_select" name="bins" id="remove_item_select"> </select> <label style="margin-top: 40px; display: none;" id="remove_item_item_label">Select an item to remove:</label> <select class="w3-select" name="items_sel" id="remove_item_item_select" style="display: none;"> </select> <div class="w3-row-padding" style="margin-top: 30px;"> <div class="w3-center"> <input type="submit" value="Remove item" class="w3-button w3-white w3-border"> </div> </div> </form> </div> </div> </div> </div> <div id="change_qty" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 25px;"> <h2>Change the quantity of an item</h2> </header> <div class="w3-container" style="margin: auto; width: 100%;"> <span class="w3-button w3-display-topright">×</span> <div class="w3-container" style="margin: auto; width: 100%;"> <form id="change_item_form" class="w3-container" > <label>Select a bin:</label> <select class="w3-select bin_select" name="bins" id="change_qty_bin_select"> </select> <label style="margin-top: 40px; display: none;" id="change_qty_label">Select an item to change:</label> <select class="w3-select" name="items_sel" id="change_qty_item_select" style="display: none;"> </select> <div style="width: 25%;" class="w3-center"> <label style="margin-top: 40px;">Change item quantity by </label> <input type="number" class="w3-input" name="num" value="0"> </div> <div class="w3-row-padding" style="margin-top: 30px;"> <div class="w3-center"> <input type="submit" value="Change item" class="w3-button w3-white w3-border"> </div> </div> </form> </div> </div> </div> </div> <div id="add_bin" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 25px;"> <h2>Add a new bin</h2> </header> <div class="w3-container" style="margin: auto; width: 100%;"> <span class="w3-button w3-display-topright">×</span> <div class="w3-container" style="margin: auto; width: 100%;"> <form id="add_new_bin_form" class="w3-container" > <label>New bin name</label> <input type="text" class="w3-input" name="bin_name" style="margin-bottom: 20px;" required> <label>RFID UID (Leave blank if none.)</label> <input type="text" value="" class="w3-input" name="rfid" style="margin-bottom: 20px;"> <label>Description</label> <input type="text" class="w3-input" name="desc" style="margin-bottom: 20px;" required> <label>Bin type (RES, CAP, etc.)</label> <input type="text" class="w3-input" name="type" style="margin-bottom: 20px;" required> <label>Is SMD?</label> <input type="radio" name="is_smd" class="w3-radio" value="1"> <label>Yes</label> <input type="radio" name="is_smd" class="w3-radio" value="0" checked> <label>No</label> </br> <label>Is it mixed? (SMD and non-SMD)</label> <input type="radio" name="is_mixed" class="w3-radio" value="1"> <label>Yes</label> <input type="radio" name="is_mixed" class="w3-radio" value="0" checked> <label>No</label> </br> <div class="w3-row-padding w3-center" style="margin-top: 20px;"> <div class="w3-half"> <input type="submit" value="Create bin" class="w3-button w3-white w3-border"> </div> <div class="w3-half"> <input type="reset" value="Reset values" class="w3-button w3-white w3-border"> </div> </div> </form> </div> </div> </div> </div> <div id="remove_bin" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 25px;"> <h2>Remove a bin (Dangerous!)</h2> </header> <div class="w3-container" style="margin: auto; width: 100%;"> <span class="w3-button w3-display-topright">×</span> <div id="remove_bin_container" class="w3-display-container w3-white"> <form id="remove_bin_form" class="w3-container" > <label>Bin:</label> <select id="bin_remove_sel" name="bin_name" class="w3-select bin_select"> </select> </br> <div class="w3-panel w3-red w3-display-container"> <span class="w3-button w3-large w3-display-topright">×</span> <h3>Danger!</h3> <p>Removing a bin also removes all associated parts!</p> </div> <div class="w3-row-padding" style="margin-top: 30px;"> <div class="w3-center"> <input type="submit" value="Remove bin" class="w3-button w3-white w3-border"> </div> </div> </form> </div> </div> </div> </div> <div id="add_bulk_item" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 50px;"> <h2>Add new items in bulk</h2> </header> <div class="w3-container" style="margin: auto; width: 400px;"> <span class="w3-button w3-display-topright">×</span> <div id="add_new_set" class="w3-display-container w3-white"> <form id="add_bulk_form" class="w3-container" > <label>Bin:</label> <select id="bin_select" name="bin_name" class="w3-select bin_select"> </select> <label>Enter values separated by a comma:</label> <textarea required id="values" name="value_str" rows="10",cols="40" value=""></textarea><br> <label>Starting quantity of each part</label> <input required type="number" class="w3-input" name="qty" value="0" min="0"> <label>Package (Leave blank if none.)</label> <input type="text" name="pkg" class="w3-input"></br> <label>Is this set of parts SMD?</label> <input type="radio" name="is_smd" class="w3-radio" value="1"> <label>Yes</label> <input type="radio" name="is_smd" class="w3-radio" value="0" checked> <label>No</label> </br> <div class="w3-row-padding"> <div class="w3-half"> <input type="submit" value="Create parts" class="w3-button w3-white w3-border"> </div> <div class="w3-half"> <input type="reset" value="Reset values" class="w3-button w3-white w3-border"> </div> </div> </form> </div> </div> </div> </div> <div id="add_one_item" class="w3-modal w3-card-4" style="width:100%;"> <div class="w3-modal-content w3-animate-top"> <header class="w3-container w3-blue-gray w3-center" style="margin-bottom: 50px;"> <h2>Add a new item</h2> </header> <div class="w3-container" style="margin: auto; width: 400px;"> <span class="w3-button w3-display-topright">×</span> <div id="add_new_set" class="w3-display-container w3-white"> <form id="add_one_form" class="w3-container" onsubmit="create_one_part('bin_add_one_select',this.item_name.value,this.qty.value, this.is_smd.value,this.pkg.value,this.val.value,this.desc.value); return false"> <label>Bin:</label> <select id="bin_add_one_select" name="bin_name" class="w3-select bin_select"> </select> <label>Name of new item</label> <input type="text" class="w3-input" name="item_name" required> <label>Starting quantity of part</label> <input type="number" class="w3-input" name="qty" value="0" min="0" required> <label>Package (Leave blank if none.)</label> <input type="text" name="pkg" class="w3-input"></br> <label>Value (Leave blank if none.)</label> <input type="text" name="val" class="w3-input"></br> <label>Item Description</label> <input type="text" name="desc" class="w3-input" required></br> <label>Is this part SMD?</label> <input type="radio" name="is_smd" class="w3-radio" value="1"> <label>Yes</label> <input type="radio" name="is_smd" class="w3-radio" value="0" checked> <label>No</label> </br> <div class="w3-row-padding"> <div class="w3-half"> <input type="submit" value="Create part" class="w3-button w3-white w3-border"> </div> <div class="w3-half"> <input type="reset" value="Reset values" class="w3-button w3-white w3-border"> </div> </div> </form> </div> </div> </div> </div> </body> </html> [/mw_shl_code] Javascript网页 [mw_shl_code=applescript,true]const ip = "ip address here"; //Make sure to change this function create_parts(bin_sel, value_str, pkg,is_smd,qty){ console.log(bin_sel); var sel_elem = document.getElementById(bin_sel); var bin_str = sel_elem.options[sel_elem.selectedIndex].value; var bin_parsed = JSON.parse(bin_str); var id = bin_parsed.id; var type = bin_parsed.type; var val_array = value_str.split(","); console.log(val_array); val_array.forEach(element => { console.log(element); var smd_modify = ""; if(is_smd==="1"){ smd_modify = "SMD" } var modifier = `${pkg} ${smd_modify}`; var dataString = { name: `${modifier} ${element} ${type}`, value: `${ele [/mw_shl_code] |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed