开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统

本篇教程内容为:通过使用Particle Photon和终端数据库以及网页界面,并采用NFC贴纸对电子组件进行追踪。

其他文章:

开源NFC模块示例(一):arduino NFC近场通讯模块的简易教程和评测
开源NFC模块示例(二):与Arduino UNO开发板的配合
开源NFC模块示例(三):Arduino NFC模块使用方法分享,PN532模块,S50卡
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统

此项目需要用到的工具材料:

硬件组件

光子(Particle Photon)物联网开发板
RC522 NFC标记阅读器
OLED 2828 262K色 全彩显示模块
Adafruit电容式触摸传感器 - MPR121
NFC贴纸* 40

软件应用程序和在线服务

Autodesk Fusion 360
粒子搭建Web IDE
MySQL
NodeJS
手动工具和制造设备
3D打印机
烙铁

故事:

目的

想象一下,作为创客空间的所有者,您可以自行组织和跟踪仓库内的设备。有时您的成员可能会借用这些组件但是并没有归还给您,或者他们将自己的工具材料带来后并将二者组装起来。这就是为什么我需要创建一个单独的库存管理系统,它使用NFC和仓储箱(bin)对具有物联网功能的组件进行组织和跟踪。
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第1张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第2张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第3张图片

演示视频

(请到原文相应处查看:http://mc.dfrobot.com.cn/thread-276715-1-1.html )

总体布局

每个bin都会被分配一个名称、描述、一般类型,以及与其贴纸相对应的NFC UID。当零件进入bin时,每个零件都会有一个名称、描述、数量、类型,以及它所属bin的ID。所有这些数据都托管在MySQL数据库中。我使用NodeJS网络服务器创建了一个云API,然后可以对MySQL数据库执行某些操作,例如创建新组件或删除bin。在硬件方面,我使用带128x128 OLED屏幕和NFC读取器的Particle Photon,以及用于虚拟按钮的MPR121。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第4张图片
我还创建了一个网页,允许完全访问API,以便能够轻松、干净地更改几乎所有关于bin或组件的内容。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第5张图片

网络服务器

我决定使用最适合我的用例的Express库,因为它允许创建简单的RESTful API,并且路径创建也非常简单。我开始使用npm安装express,以及cors和mysql。然后我用“require('包名package_name ')”将它们放置在顶部全局定义程序里面。我使用MySQL库的createPool函数连接到MySQL数据库,因为它能够轻松安全地创建和释放连接。每个API路径都有自己的功能,其中“app.post”用于POST请求,“app.get”用于GET请求。

字符串是发送数据的路径,例如“/parts/get_all_bins”。函数内容各不相同,但通常每个函数都建立与数据库的连接,解析请求数据,并执行某项查询。在数据库和设备之间添加缓冲区会创建一层安全控制区。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第6张图片

MySQL数据库

那么虽然目前存在一种访问和更改数据的方法,但是数据究竟存储在何处或如何存储?当我安装MySQL数据库时,我还安装了MySQL Workbench,它允许用户对其数据库进行管理。我创建了名为“components”的新模式,并创建了两个表:parts和bin。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第7张图片
每张表都需要不同的列,因为bin没有具体数量,而且组件不需要NFC UID。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第8张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第9张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第10张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第11张图片
我还创建了需要登录密码的新用户,以便与NodeJS服务器同时使用。如果有人获得对服务器代码的访问权限,那么执行此操作而不是使用root密码会大大提高安全性。

NFC RFID标签

当我第一次开始这个项目时,我只有几张NFC卡,所以我必须找到一种新的数据存储和扫描方法。然后我去了AliExpress寻找更好的媒介。我看到了NFC贴纸,它贴有一个非常小的天线和芯片,但是整个纸张非常薄而且很小。这样我们就可以将它们粘在bin上并轻松读取。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第12张图片

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第13张图片

硬件

那么bin究竟以何种方式进行扫描,数量如何变化?对于这个问题,我使用RC522 RFID阅读器读取NFC标签。为了显示数据和指令,我使用了一个使用SSD1351控制器的128x128 OLED屏幕。由于此项目适用于创客空间,我希望避免使用物理按钮,因为它们可能会出现磨损。MPR121电容式触控板价格低廉并且具有I2C接口,最终被我选用。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第14张图片

它最多可以处理12个不同的频道。在我的设计方案中,我增加3个附有1/4英寸铜带的地方。这些铜片在触摸时可以充当按钮。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第15张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第16张图片

硬件代码

由于系统需要通过一系列繁琐的步骤进行创建,因此我开发了一个系统,该系统使用状态机对显示的页面进行控制。它按照以下顺序依次排列:搜索选项卡->选择bin ->显示bin ->显示组件->更改数量。为了解析来自Web服务器的响应,我使用了SparkJson库。在每个阶段,请求会自动生成并将其发送到Web服务器。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第17张图片

网页

这是整个项目中最难更正的部分。它包含三个组件:HTML、JavaScript和CSS。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第18张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第19张图片

由于我还是CSS新手,我使用的是W3 School的W3.CSS课程。为了确保界面的简洁,我制作了一个简单的按钮网格,每个按钮对应一个弹出的模态卡。每张模态卡右上角都有一个关闭按钮。列表箱和列表项等按钮显示一个在单击时更新的列表中。添加新项目和添加bin等按钮都包含在一个表单内。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第20张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第21张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第22张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第23张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第24张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第25张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第26张图片
开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第27张图片
JavaScript代码过于复杂,无法在本文中进行解释,但是它基本上包含在提交表单时调用的各种函数中。某些函数还会填充选择元素和表。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第28张图片

用法

如需使用该系统,用户将首先通过输入其名称和其他数据来填充他们所拥有的bin列表。然后按照类似的方式创建组件。如有需要,通过一个按钮即可批量创建组件,例如塞满各种电阻值的bin。一旦所有事情准备就绪,那么现在就可以使用photon对bin进行扫描了。

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第29张图片

未来计划

在未来,我希望扩展系统,使其包括登录和所有权方面的内容。用户可以扫描他们的makerspace RFID卡,然后访问他们自己的个人bin。

原理图

开源NFC模块示例(四):如何制作Makerspace NFC组件管理系统_第30张图片

代码

物理ReaderC/C++

[/align]// This #include statement was automatically added by the Particle IDE.
 
#include 
 
  
 
// This #include statement was automatically added by the Particle IDE.
 
#include 
 
  
 
// This #include statement was automatically added by the Particle IDE.
 
#include 
 
  
 
#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 (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 ");
 
            }
 
            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 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[i] < 0x10 ? " 0" : " ");
 
            Serial.print(mfrc522.uid.uidByte[i], HEX);
 
            current_card.id_string += mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ";
 
            current_card.id_string += String(mfrc522.uid.uidByte[i], HEX);
 
            current_card.id_digits[i] = mfrc522.uid.uidByte[i];
 
            }
 
            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);

HTML网页


 

 
    Part Tracker
 
    
 
    
 
    
 
    
 
    
 

 

 
    

Part Tracker Main Page

View all parts

×
Name ID Value Quantity Description Package Bin ID Is SMD?

View all bins

×
Name ID RFID UID Type Description Is SMD? Is mixed?

View parts from bin

×

Remove an item

×

Change the quantity of an item

×

Add a new bin

×


Remove a bin (Dangerous!)

×

×

Danger!

Removing a bin also removes all associated parts!

Add new items in bulk

×



Add a new item

×




Javascript网页

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

推荐项目阅读:
使用SPRESENSE电路板的POV显示器
【ardunio项目】如何制作深受儿童喜爱的木制收音机
Arduino“反应计时器” - 我的孩子喜欢玩这个
ESP32项目:邮件警报
物联网植物监测仪,用 Particle Photon制作、IFTTT监测

更多:创客项目

你可能感兴趣的:(NFC)