@@ -101,7 +101,7 @@ public class MainActivity extends FragmentActivity implements View.OnClickListen | |||
*/ | |||
@Override | |||
protected void onDestroy() { | |||
//MQTT.get().ConnMqttBroken(false);//释放mqtt | |||
MQTT.get().ConnMqttBroken(false);//释放mqtt | |||
ModbusTcpHelper.get().release();//释放modbus | |||
super.onDestroy(); | |||
} | |||
@@ -151,7 +151,7 @@ public class MainActivity extends FragmentActivity implements View.OnClickListen | |||
//PLC数据监控 | |||
ModbusTcpServer.get().Connect(ConfigName.getInstance().Address, ConfigName.getInstance().Post); | |||
//MQTT数据监听 | |||
//OrderServer.Get().MqttInit(); | |||
OrderServer.Get().MqttInit(); | |||
//消息中心 | |||
RegisterMessage(); | |||
} | |||
@@ -274,11 +274,11 @@ public class MainActivity extends FragmentActivity implements View.OnClickListen | |||
for (SuOrderA item : order.orderDetail)//新增子订单 | |||
{ | |||
BPA_SUBORDER suborder = new BPA_SUBORDER(); | |||
suborder.id=item.id; | |||
suborder.deviceID = ConfigName.getInstance().DeviceId; | |||
suborder.userID = ConfigName.getInstance().user.userID; | |||
suborder.orderID = item.orderInfo_Id; | |||
suborder.goodsID = QueryDB.GetGoodsALL().get(0).id;//"2f064965-8d63-4b00-9d14-c8d118791898";//item.goods_Id; | |||
suborder.goodsID = item.goods_Id;//QueryDB.GetGoodsALL().get(0).id;//"2f064965-8d63-4b00-9d14-c8d118791898";//item.goods_Id; | |||
suborder.number = 1; | |||
suborder.status = 0; | |||
suborder.goodImg = item.goodImg; | |||
@@ -382,6 +382,8 @@ public class MainActivity extends FragmentActivity implements View.OnClickListen | |||
} | |||
} | |||
}); | |||
} | |||
//endregion | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.example.bpa.Model; | |||
import java.util.Date; | |||
/** | |||
* 消息包 | |||
*/ | |||
public class BPAPackage { | |||
public int MessageId; | |||
public byte MessageVersion; | |||
public int ClientId; | |||
public int ClientType;//9 是MORKT | |||
public String Timestamp; | |||
public PushDeviceGoods Message; | |||
} |
@@ -20,4 +20,8 @@ public class BatchingsInfo { | |||
/// </summary> | |||
public String BomId; | |||
public boolean IsReplace; | |||
/// <summary> | |||
/// 商品关联BomID | |||
/// </summary> | |||
public String GoodsBomId; | |||
} |
@@ -8,4 +8,8 @@ public class GoodsBom { | |||
/// 是否主料配方 | |||
/// </summary> | |||
public boolean IsMain; | |||
/// <summary> | |||
/// 商品关联BomID | |||
/// </summary> | |||
public String GoodsBomId; | |||
} |
@@ -3,7 +3,7 @@ package com.example.bpa.Model; | |||
public class OrderStatusChange { | |||
public String SuborderId; | |||
/** | |||
* 3 等待制作 4 制作中 5 制作完成等待取餐 6 取餐完成 | |||
* 4 制作中 5 制作完成等待取餐 6 取餐完成 11废弃 | |||
*/ | |||
public Integer CookingStatus ; | |||
@@ -13,14 +13,12 @@ import com.example.bpa.db.mode.BPA_LOG; | |||
import com.example.bpa.db.mode.BPA_SILOS; | |||
import com.example.bpa.db.mode.BPA_SILOSANDMATERIAL; | |||
import com.example.bpa.db.mode.BPA_SUBORDER; | |||
import com.example.bpa.db.mode.BPA_SUGAR; | |||
import com.example.bpa.db.mode.BPA_USER; | |||
import com.example.bpa.helper.AES; | |||
import com.example.bpa.helper.MessageLog; | |||
import com.example.bpa.helper.ModbusTcpServer; | |||
import com.example.bpa.helper.SdCart; | |||
import com.example.bpa.helper.ToastUtil; | |||
import com.example.bpa.service.BusinessServer; | |||
import com.example.bpa.service.OrderServer; | |||
import com.example.bpa.view.mode.AlertLogEnum; | |||
import com.example.bpa.view.mode.UserLogEnum; | |||
@@ -41,7 +39,8 @@ public class ICSApp extends Application { | |||
InitDBdata(); | |||
//4.初始化Main | |||
Main.getInstance(); | |||
//BusinessServer.Get().test(); | |||
BusinessServer.Get().test(); | |||
//MessageLog.ShowAlertMessage(AlertLogEnum.传感器异常日志,"传感器异常"); | |||
//MessageLog.ShowAlertMessage(AlertLogEnum.异常订单未制作日志,"异常订单未制作日志"); | |||
//MessageLog.ShowAlertMessage(AlertLogEnum.料仓缺料日志,"料仓缺料日志"); | |||
@@ -12,7 +12,6 @@ import com.example.bpa.db.QueryDB; | |||
import com.example.bpa.db.mode.BPA_SYSTEMSET; | |||
import com.example.bpa.db.mode.BPA_USER; | |||
import com.example.bpa.helper.AES; | |||
import com.example.bpa.helper.AESCBCUtils; | |||
import com.example.bpa.helper.ConfigUtil; | |||
import com.example.bpa.helper.HttpUtils; | |||
import com.example.bpa.helper.Json; | |||
@@ -238,7 +237,7 @@ public class Main { | |||
public void GetOrder(String orderNumber) | |||
{ | |||
//https://bpa.black-pa.com:21527/order/order/fullorderbynumber/202305111151562071 | |||
orderNumber="202306051240019217"; | |||
orderNumber="454196868008775680"; | |||
//202202211310398967 | |||
//String api="https://bpa.black-pa.com:21528/kitchen/api/member-helper/memberinfobywechat/987654321"; | |||
Log.i("查询用户接口", ConfigName.getInstance().SaasAddress+ConfigName.getInstance().GetOrder+orderNumber); | |||
@@ -51,7 +51,7 @@ public class ConfigName { | |||
/** | |||
* 店铺设备号 | |||
*/ | |||
public String AutKey="95"; | |||
public String AutKey="152.146"; | |||
/** | |||
* 店铺设备号 | |||
*/ | |||
@@ -78,7 +78,7 @@ public class ConfigName { | |||
/** | |||
* 订阅主题 | |||
*/ | |||
public String mqtt_topic="DOWN/TMC/BUSINESS/"; | |||
public String mqtt_topic="DOWN/MORKT/BUSINESS/"; | |||
//endregion | |||
//region 环境配置 | |||
@@ -3,8 +3,10 @@ package com.example.bpa.config; | |||
import android.app.Activity; | |||
import com.example.bpa.Model.OrderA; | |||
import com.example.bpa.Model.OrderStatusChange; | |||
import com.example.bpa.Model.ResultA; | |||
import com.example.bpa.R; | |||
import com.example.bpa.app.Main; | |||
import com.example.bpa.db.mode.BPA_SUBORDER; | |||
import com.example.bpa.service.DeviceData; | |||
import com.example.bpa.db.QueryDB; | |||
@@ -150,7 +152,6 @@ public class DataBus { | |||
orderadapter.refresh(); | |||
} | |||
} | |||
}catch(Exception e){ | |||
} | |||
} | |||
@@ -207,6 +208,10 @@ public class DataBus { | |||
GoodsMake.get(m).makeProcess=(count/ GoodsMake.get(m).recipes.size())*100; | |||
goodmakeadapter.refresh(); | |||
OrderStatusChange change=new OrderStatusChange(); | |||
change.SuborderId=GoodsMake.get(m).subOrder.id; | |||
change.CookingStatus=4; | |||
Main.getInstance().SetOrderChanged(change); | |||
return; | |||
} | |||
} | |||
@@ -248,9 +253,14 @@ public class DataBus { | |||
if(good!=null) | |||
{ | |||
//GoodsMakeOver.add(good); | |||
GoodsMake.remove(good); | |||
goodmakeadapter.refresh(); | |||
OrderStatusChange change=new OrderStatusChange(); | |||
change.SuborderId=good.subOrder.id; | |||
change.CookingStatus=6; | |||
change.GoodName=good.good.name; | |||
Main.getInstance().SetOrderChanged(change); | |||
} | |||
}catch(Exception e){ | |||
} | |||
@@ -403,7 +403,7 @@ public class QueryDB { | |||
* @return | |||
*/ | |||
public static ArrayList<BPA_SILOSANDMATERIAL> GetSilosAndMaterialALL() { | |||
String orderby = Desc_Sort_Up + ',' + Desc_Time_Up;//先按排序 创建时间倒序 | |||
String orderby = Desc_Time_Up;//先按排序 创建时间倒序 | |||
String where = "isDelete=?"; | |||
String[] args = new String[]{"0"}; | |||
ArrayList<BPA_SILOSANDMATERIAL> data = new ArrayList<>(); | |||
@@ -607,6 +607,25 @@ public class QueryDB { | |||
return data.size() > 0; | |||
} | |||
/** | |||
* 判断商品数据是否存在 | |||
* | |||
* @param id | |||
* @return | |||
*/ | |||
public static boolean GetGoodsIDIs(String id) { | |||
boolean isSucess = false; | |||
String orderby = Desc_Time_Up;//出料顺序 | |||
String where = "isDelete=? and id=?"; | |||
String[] args = new String[]{"0", id}; | |||
ArrayList<BPA_GOODS> data = new ArrayList<>(); | |||
ArrayList<Object> obj = Get(BPA_GOODS.class, where, args, orderby); | |||
for (Object k : obj) { | |||
data.add((BPA_GOODS) k); | |||
} | |||
return data.size() > 0; | |||
} | |||
/** | |||
* 根据排序查询商品 | |||
* | |||
@@ -723,14 +742,13 @@ public class QueryDB { | |||
for (Object item : obj) { | |||
BPA_GOODSRECIPE k = (BPA_GOODSRECIPE) item; | |||
String name = ""; | |||
if (k.materialType ==1){ | |||
BPA_MATERIAL res = GetMaterialID(k.materialID); | |||
if (res!= null) { name = GetMaterialID(k.materialID).name;} | |||
}else if (k.materialType ==2){ | |||
BPA_SUGAR res = GetsugarId(k.materialID); | |||
if (res!= null) { name = GetsugarId(k.materialID).sugarName;} | |||
} | |||
BPA_MATERIAL res = GetMaterialID(k.materialID); | |||
if (res!= null) { name = GetMaterialID(k.materialID).name;} | |||
// if (k.materialType ==1){ | |||
// }else if (k.materialType ==2){ | |||
// BPA_SUGAR res = GetsugarId(k.materialID); | |||
// if (res!= null) { name = GetsugarId(k.materialID).sugarName;} | |||
// } | |||
if (name != "") { | |||
ResGoodsRecipe par = new ResGoodsRecipe(); | |||
@@ -10,6 +10,7 @@ import java.io.FileInputStream; | |||
import java.io.FileNotFoundException; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.math.BigInteger; | |||
import java.nio.charset.Charset; | |||
import java.nio.charset.StandardCharsets; | |||
@@ -22,243 +23,146 @@ import javax.crypto.spec.SecretKeySpec; | |||
/** | |||
* AES 对称加密算法,加解密工具类 | |||
*/ | |||
public class AES { | |||
private static final String TAG = AES.class.getSimpleName() + " --> "; | |||
/** | |||
* 加密算法 | |||
*/ | |||
private static final String KEY_ALGORITHM = "AES"; | |||
public class AES { | |||
public static String key="bpa20210418bpa20210418bpa*******"; | |||
/** | |||
* AES 的 密钥长度,32 字节,范围:16 - 32 字节 | |||
* 加密 | |||
* @return 加密后的字符串 | |||
*/ | |||
public static final int SECRET_KEY_LENGTH = 32; | |||
public static String Encrypt(String src) throws Exception { | |||
// 判断密钥是否为空 | |||
if (key == null) { | |||
System.out.print("密钥不能为空"); | |||
return null; | |||
} | |||
/** | |||
* 字符编码 | |||
*/ | |||
private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8; | |||
byte[] data = key.getBytes("utf-8"); | |||
SecretKeySpec skeySpec = new SecretKeySpec(data, "AES"); | |||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 算法/模式/补码方式 | |||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec); | |||
byte[] encrypted = cipher.doFinal(src.getBytes("utf-8")); | |||
/** | |||
* 秘钥长度不足 16 个字节时,默认填充位数 | |||
*/ | |||
private static final String DEFAULT_VALUE = "0"; | |||
/** | |||
* 加解密算法/工作模式/填充方式 | |||
*/ | |||
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; | |||
/** | |||
* 加密密码,长度:16 或 32 个字符(随便定义) | |||
*/ | |||
private static final String secretKey = "bpa20210418bpa20210418bpa*******"; | |||
/** | |||
* AES 加密 | |||
* | |||
* @param data 待加密内容 | |||
* @return 返回Base64转码后的加密数据 | |||
*/ | |||
public static String encrypt(String data) { | |||
try { | |||
//创建密码器 | |||
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); | |||
//初始化为加密密码器 | |||
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(secretKey)); | |||
byte[] encryptByte = cipher.doFinal(data.getBytes(CHARSET_UTF8)); | |||
// 将加密以后的数据进行 Base64 编码 | |||
return base64Encode(encryptByte); | |||
} catch (Exception e) { | |||
handleException(e); | |||
} | |||
return null; | |||
//return new Base64().encodeToString(encrypted);//base64 | |||
return binary(encrypted, 16); //十六进制 | |||
} | |||
/** | |||
* AES 解密 | |||
* | |||
* @param base64Data 加密的密文 Base64 字符串 | |||
* 解密 | |||
* @param src 解密字符串 | |||
* @return 解密后的字符串 | |||
*/ | |||
public static String decrypt(String base64Data) { | |||
public static String Decrypt(String src) throws Exception { | |||
try { | |||
byte[] data = base64Decode(base64Data); | |||
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); | |||
//设置为解密模式 | |||
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(secretKey)); | |||
//执行解密操作 | |||
byte[] result = cipher.doFinal(data); | |||
return new String(result, CHARSET_UTF8); | |||
} catch (Exception e) { | |||
handleException(e); | |||
// 判断Key是否正确 | |||
if (key == null) { | |||
System.out.print("Key为空null"); | |||
return null; | |||
} | |||
byte[] data = key.getBytes("utf-8"); | |||
SecretKeySpec skeySpec = new SecretKeySpec(data, "AES"); | |||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); | |||
cipher.init(Cipher.DECRYPT_MODE, skeySpec); | |||
byte[] encrypted1 = toByteArray(src);//十六进制 | |||
try { | |||
byte[] original = cipher.doFinal(encrypted1); | |||
String originalString = new String(original,"utf-8"); | |||
return originalString; | |||
} catch (Exception e) { | |||
System.out.println(e.toString()); | |||
return null; | |||
} | |||
} catch (Exception ex) { | |||
System.out.println(ex.toString()); | |||
return null; | |||
} | |||
return null; | |||
} | |||
/** | |||
* 使用密码获取 AES 秘钥 | |||
* 将byte[]转为各种进制的字符串 | |||
* @param bytes byte[] | |||
* @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制 | |||
* @return 转换后的字符串 | |||
*/ | |||
public static SecretKeySpec getSecretKey(String secretKey) { | |||
secretKey = toMakeKey(secretKey, SECRET_KEY_LENGTH, DEFAULT_VALUE); | |||
return new SecretKeySpec(secretKey.getBytes(CHARSET_UTF8), KEY_ALGORITHM); | |||
public static String binary(byte[] bytes, int radix){ | |||
return new BigInteger(1, bytes).toString(radix); // 这里的1代表正数 | |||
} | |||
/** | |||
* 如果 AES 的密钥小于 {@code length} 的长度,就对秘钥进行补位,保证秘钥安全。 | |||
* 16进制的字符串表示转成字节数组 | |||
* | |||
* @param secretKey 密钥 key | |||
* @param length 密钥应有的长度 | |||
* @param text 默认补的文本 | |||
* @return 密钥 | |||
*/ | |||
private static String toMakeKey(String secretKey, int length, String text) { | |||
// 获取密钥长度 | |||
int strLen = secretKey.length(); | |||
// 判断长度是否小于应有的长度 | |||
if (strLen < length) { | |||
// 补全位数 | |||
StringBuilder builder = new StringBuilder(); | |||
// 将key添加至builder中 | |||
builder.append(secretKey); | |||
// 遍历添加默认文本 | |||
for (int i = 0; i < length - strLen; i++) { | |||
builder.append(text); | |||
} | |||
// 赋值 | |||
secretKey = builder.toString(); | |||
* @param hexString 16进制格式的字符串 | |||
* @return 转换后的字节数组 | |||
**/ | |||
public static byte[] toByteArray(String hexString) { | |||
if (hexString.isEmpty()) | |||
throw new IllegalArgumentException("this hexString must not be empty"); | |||
hexString = hexString.toLowerCase(); | |||
final byte[] byteArray = new byte[hexString.length() / 2]; | |||
int k = 0; | |||
for (int i = 0; i < byteArray.length; i++) {//因为是16进制,最多只会占用4位,转换成字节需要两个16进制的字符,高位在先 | |||
byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff); | |||
byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff); | |||
byteArray[i] = (byte) (high << 4 | low); | |||
k += 2; | |||
} | |||
return secretKey; | |||
return byteArray; | |||
} | |||
/** | |||
* 将 Base64 字符串 解码成 字节数组 | |||
*/ | |||
public static byte[] base64Decode(String data) { | |||
return Base64.decode(data, Base64.NO_WRAP); | |||
} | |||
/** | |||
* 将 字节数组 转换成 Base64 编码 | |||
*/ | |||
public static String base64Encode(byte[] data) { | |||
return Base64.encodeToString(data, Base64.NO_WRAP); | |||
} | |||
/** | |||
* 处理异常 | |||
*/ | |||
private static void handleException(Exception e) { | |||
e.printStackTrace(); | |||
Log.e(TAG, TAG + e); | |||
} | |||
/** | |||
* 对文件进行AES加密 | |||
* | |||
* @param sourceFile 待加密文件 | |||
* @param dir 加密后的文件存储路径 | |||
* @param toFileName 加密后的文件名称 | |||
* @param secretKey 密钥 | |||
* @return 加密后的文件 | |||
* bytes转换成十六进制字符串 | |||
* @param b byte数组 | |||
* @return String 每个Byte值之间空格分隔 | |||
*/ | |||
public static File encryptFile(File sourceFile, String dir, String toFileName, String secretKey) { | |||
try { | |||
// 创建加密后的文件 | |||
File encryptFile = new File(dir, toFileName); | |||
// 根据文件创建输出流 | |||
FileOutputStream outputStream = new FileOutputStream(encryptFile); | |||
// 初始化 Cipher | |||
Cipher cipher = initFileAESCipher(secretKey, Cipher.ENCRYPT_MODE); | |||
// 以加密流写入文件 | |||
CipherInputStream cipherInputStream = new CipherInputStream( | |||
new FileInputStream(sourceFile), cipher); | |||
// 创建缓存字节数组 | |||
byte[] buffer = new byte[1024 * 2]; | |||
// 读取 | |||
int len; | |||
// 读取加密并写入文件 | |||
while ((len = cipherInputStream.read(buffer)) != -1) { | |||
outputStream.write(buffer, 0, len); | |||
outputStream.flush(); | |||
} | |||
// 关闭加密输入流 | |||
cipherInputStream.close(); | |||
closeStream(outputStream); | |||
return encryptFile; | |||
} catch (Exception e) { | |||
handleException(e); | |||
public static String byte2HexStr(byte[] b) | |||
{ | |||
String stmp=""; | |||
StringBuilder sb = new StringBuilder(""); | |||
for (int n=0;n<b.length;n++) | |||
{ | |||
stmp = Integer.toHexString(b[n] & 0xFF); | |||
sb.append((stmp.length()==1)? "0"+stmp : stmp); | |||
sb.append(" "); | |||
} | |||
return null; | |||
return sb.toString().toUpperCase().trim(); | |||
} | |||
/** | |||
* AES解密文件 | |||
* | |||
* @param sourceFile 源加密文件 | |||
* @param dir 解密后的文件存储路径 | |||
* @param toFileName 解密后的文件名称 | |||
* @param secretKey 密钥 | |||
/* | |||
* 16进制字符串转字节数组 | |||
*/ | |||
public static File decryptFile(File sourceFile, String dir, String toFileName, String secretKey) { | |||
try { | |||
// 创建解密文件 | |||
File decryptFile = new File(dir, toFileName); | |||
// 初始化Cipher | |||
Cipher cipher = initFileAESCipher(secretKey, Cipher.DECRYPT_MODE); | |||
// 根据源文件创建输入流 | |||
FileInputStream inputStream = new FileInputStream(sourceFile); | |||
// 获取解密输出流 | |||
CipherOutputStream cipherOutputStream = new CipherOutputStream( | |||
new FileOutputStream(decryptFile), cipher); | |||
// 创建缓冲字节数组 | |||
byte[] buffer = new byte[1024 * 2]; | |||
int len; | |||
// 读取解密并写入 | |||
while ((len = inputStream.read(buffer)) >= 0) { | |||
cipherOutputStream.write(buffer, 0, len); | |||
cipherOutputStream.flush(); | |||
public static byte[] hexString2Bytes(String hex) { | |||
if ((hex == null) || (hex.equals(""))){ | |||
return null; | |||
} | |||
else if (hex.length()%2 != 0){ | |||
return null; | |||
} | |||
else{ | |||
hex = hex.toUpperCase(); | |||
int len = hex.length()/2; | |||
byte[] b = new byte[len]; | |||
char[] hc = hex.toCharArray(); | |||
for (int i=0; i<len; i++){ | |||
int p=2*i; | |||
b[i] = (byte) (charToByte(hc[p]) << 4 | charToByte(hc[p+1])); | |||
} | |||
// 关闭流 | |||
cipherOutputStream.close(); | |||
closeStream(inputStream); | |||
return decryptFile; | |||
} catch (IOException e) { | |||
handleException(e); | |||
return b; | |||
} | |||
return null; | |||
} | |||
/** | |||
* 初始化 AES Cipher | |||
* | |||
* @param secretKey 密钥 | |||
* @param cipherMode 加密模式 | |||
* @return 密钥 | |||
*/ | |||
private static Cipher initFileAESCipher(String secretKey, int cipherMode) { | |||
try { | |||
// 创建密钥规格 | |||
SecretKeySpec secretKeySpec = getSecretKey(secretKey); | |||
// 获取密钥 | |||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |||
// 初始化 | |||
cipher.init(cipherMode, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); | |||
return cipher; | |||
} catch (Exception e) { | |||
handleException(e); | |||
} | |||
return null; | |||
} | |||
/** | |||
* 关闭流 | |||
* | |||
* @param closeable 实现Closeable接口 | |||
/* | |||
* 字符转换为字节 | |||
*/ | |||
private static void closeStream(Closeable closeable) { | |||
try { | |||
if (closeable != null) closeable.close(); | |||
} catch (Exception e) { | |||
handleException(e); | |||
} | |||
private static byte charToByte(char c) { | |||
return (byte) "0123456789ABCDEF".indexOf(c); | |||
} | |||
} |
@@ -1,101 +0,0 @@ | |||
package com.example.bpa.helper; | |||
import android.text.TextUtils; | |||
import android.util.Base64; | |||
import android.util.Log; | |||
import javax.crypto.Cipher; | |||
import javax.crypto.spec.IvParameterSpec; | |||
import javax.crypto.spec.SecretKeySpec; | |||
public class AESCBCUtils { | |||
private static final String TAG = "AESCBCUtils"; | |||
// CBC(Cipher Block Chaining, 加密快链)模式,PKCS5Padding补码方式 | |||
// AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式 | |||
/** | |||
* 加解密算法/工作模式/填充方式 | |||
*/ | |||
private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding"; | |||
// AES 加密 | |||
private static final String AES = "AES"; | |||
private static final String aesSecretKey="bpa20210418bpa20210418bpa*******"; | |||
// 密钥偏移量 | |||
//private static final String mstrIvParameter = "1234567890123456"; | |||
/* key必须为16位,可更改为自己的key */ | |||
//String mstrTestKey = "1234567890123456"; | |||
// 加密 | |||
/** | |||
* AES 加密 | |||
* | |||
* @param strKey 加密密钥 | |||
* @param strClearText 待加密内容 | |||
* @param mstrIvParameter 密钥偏移量 | |||
* @return 返回Base64转码后的加密数据 | |||
*/ | |||
public static String encrypt_AES(String strKey, String strClearText, String mstrIvParameter) { | |||
try { | |||
byte[] raw = strKey.getBytes(); | |||
// 创建AES密钥 | |||
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES); | |||
// 创建密码器 | |||
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING); | |||
// 创建偏移量 | |||
IvParameterSpec iv = new IvParameterSpec(mstrIvParameter.getBytes()); | |||
// 初始化加密器 | |||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); | |||
// 执行加密操作 | |||
byte[] cipherText = cipher.doFinal(strClearText.getBytes()); | |||
//Log.d(TAG, "encrypt result(not BASE64): " + cipherText.toString()); | |||
String strBase64Content = Base64.encodeToString(cipherText, Base64.DEFAULT); // encode it by BASE64 again | |||
//Log.d(TAG, "encrypt result(BASE64): " + strBase64Content); | |||
strBase64Content = strBase64Content.replaceAll(System.getProperty("line.separator"), ""); | |||
return strBase64Content; | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return null; | |||
} | |||
// 解密 | |||
/** | |||
* AES 解密 | |||
* | |||
* @param strKey 解密密钥 | |||
* @param strCipherText 待解密内容 | |||
* @param mstrIvParameter 偏移量 | |||
* @return 返回Base64转码后的加密数据 | |||
*/ | |||
public static String decrypt(String strKey, String strCipherText, String mstrIvParameter) throws Exception { | |||
try { | |||
byte[] raw = strKey.getBytes("ASCII"); | |||
// 创建AES秘钥 | |||
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES); | |||
// 创建密码器 | |||
Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING); | |||
// 创建偏移量 | |||
IvParameterSpec iv = new IvParameterSpec(mstrIvParameter.getBytes()); | |||
// 初始化解密器 | |||
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); | |||
// 执行解密操作 | |||
byte[] cipherText = Base64.decode(strCipherText, Base64.DEFAULT); // decode by BASE64 first | |||
//Log.d(TAG, "BASE64 decode result(): " + cipherText.toString()); | |||
byte[] clearText = cipher.doFinal(cipherText); | |||
String strClearText = new String(clearText); | |||
//Log.d(TAG, "decrypt result: " + strClearText); | |||
return strClearText; | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return null; | |||
} | |||
} |
@@ -327,7 +327,7 @@ public class ModbusTcpServer { | |||
try { | |||
ReadHoldingRegistersResponse res = ModbusTcpHelper.get().syncReadHoldingRegisters(1, add, length); | |||
byte[] data = res.getData(); | |||
byte[] data1= Arrays.copyOfRange(data, 0, 36); | |||
byte[] data1= Arrays.copyOfRange(data, 0, 18); | |||
//36 GUID 18 Number | |||
String id=""; | |||
try { | |||
@@ -143,15 +143,15 @@ public class DeviceData { | |||
}); | |||
//读取实时状态 | |||
// ModbusTcpServer.get().ReadStatus("VW382", 3, data -> { | |||
// for (int i = 0; i < data.length; i++) { | |||
// byte status=data[i];//0x92 | |||
// IoStatus.put(i*4+0, ByteHelper.getBit(status,0)==1); | |||
// IoStatus.put(i*4+1, ByteHelper.getBit(status,1)==1); | |||
// IoStatus.put(i*4+2, ByteHelper.getBit(status,2)==1); | |||
// IoStatus.put(i*4+3, ByteHelper.getBit(status,3)==1); | |||
// } | |||
// }); | |||
ModbusTcpServer.get().ReadStatus("VW382", 3, data -> { | |||
for (int i = 0; i < data.length; i++) { | |||
byte status=data[i];//0x92 | |||
IoStatus.put(i*4+0, ByteHelper.getBit(status,0)==1); | |||
IoStatus.put(i*4+1, ByteHelper.getBit(status,1)==1); | |||
IoStatus.put(i*4+2, ByteHelper.getBit(status,2)==1); | |||
IoStatus.put(i*4+3, ByteHelper.getBit(status,3)==1); | |||
} | |||
}); | |||
//配料完成 M0.3 | |||
CompleteListen("M0.3", "配料完成", OnChargeMixtureCompleteNotify); | |||
@@ -1,17 +1,39 @@ | |||
package com.example.bpa.service; | |||
import android.util.Log; | |||
import com.example.bpa.Model.BPAPackage; | |||
import com.example.bpa.Model.BPA_GoodsInfo; | |||
import com.example.bpa.Model.BatchingsInfo; | |||
import com.example.bpa.Model.Batchingstechnology; | |||
import com.example.bpa.Model.GoodsBom; | |||
import com.example.bpa.Model.IMessage; | |||
import com.example.bpa.Model.IRun; | |||
import com.example.bpa.Model.IThread; | |||
import com.example.bpa.Model.PushDeviceGoods; | |||
import com.example.bpa.config.ConfigName; | |||
import com.example.bpa.db.QueryDB; | |||
import com.example.bpa.db.mode.BPA_GOODS; | |||
import com.example.bpa.db.mode.BPA_GOODSRECIPE; | |||
import com.example.bpa.db.mode.BPA_MATERIAL; | |||
import com.example.bpa.db.mode.BPA_SILOSANDMATERIAL; | |||
import com.example.bpa.db.mode.BPA_SUBORDER; | |||
import com.example.bpa.helper.AES; | |||
import com.example.bpa.helper.Json; | |||
import com.example.bpa.helper.MQTT; | |||
import com.example.bpa.helper.MessageLog; | |||
import com.example.bpa.helper.ThreadManager; | |||
import com.example.bpa.view.mode.ResReceiveOrder; | |||
import java.text.SimpleDateFormat; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.Date; | |||
import java.util.IdentityHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.concurrent.ConcurrentLinkedQueue; | |||
/** | |||
@@ -66,26 +88,47 @@ public class OrderServer { | |||
*/ | |||
public void MqttInit() | |||
{ | |||
String ddid=ConfigName.getInstance().AutKey; | |||
String devid=ConfigName.getInstance().AutKey; | |||
if(ConfigName.getInstance().AutKey.contains(".")) | |||
{ | |||
String[] str= ConfigName.getInstance().AutKey.split("[.]"); | |||
ddid=str[0]; | |||
devid=str[1]; | |||
} | |||
//消息回调 | |||
String finalDevid = devid; | |||
MQTT.get().callback=new IMessage() { | |||
@Override | |||
public void MessageRecive(String topic, String Message) { | |||
MessageLog.ShowInfo("收到主题:"+topic+",数据:"+Message); | |||
try { | |||
if(!Message.isEmpty()) | |||
{ | |||
ResReceiveOrder model=new Json<ResReceiveOrder>().jsonToobject(ResReceiveOrder.class,((String)Message)); | |||
Commoditys.offer(model); | |||
String msg= new AES().Decrypt(Message); | |||
if(!msg.isEmpty()) | |||
{ | |||
BPAPackage model=new Json<BPAPackage>().jsonToobject(BPAPackage.class,((String)msg)); | |||
if((model.ClientId+"").equals(finalDevid) && model.ClientType==9) | |||
{ | |||
MessageLog.ShowInfo("收到远程更新数据通知!"); | |||
RefreshTheData(model.Message); | |||
} | |||
} | |||
} | |||
} catch (Exception e) { | |||
Log.d("1", "MessageRecive: "); | |||
} | |||
} | |||
}; | |||
//连接成功标志 | |||
String finalDdid = ddid; | |||
MQTT.get().ConnectOk=new IRun() { | |||
@Override | |||
public void Run() { | |||
String[] Str={ConfigName.getInstance().mqtt_topic+ConfigName.getInstance().AutKey}; | |||
String[] Str={ConfigName.getInstance().mqtt_topic+ finalDdid}; | |||
MQTT.get().Subscrib(Str); | |||
} | |||
}; | |||
@@ -122,5 +165,113 @@ public class OrderServer { | |||
} | |||
}); | |||
} | |||
/** | |||
* 刷新数据 | |||
* @param data | |||
*/ | |||
public void RefreshTheData(PushDeviceGoods data) | |||
{ | |||
try { | |||
//1.更新商品数据 | |||
for (BPA_GOODS item:QueryDB.GetGoodsALL()) | |||
{ | |||
QueryDB.DeleteGoods(item); | |||
} | |||
for (BPA_GoodsInfo item:data.GoodsInfos) | |||
{ | |||
//if(!QueryDB.GetGoodsIDIs(item.Id)) | |||
{ | |||
BPA_GOODS goodx = new BPA_GOODS(); | |||
goodx.id=item.Id; | |||
goodx.name = item.Goods_Name; | |||
goodx.sort = item.Goods_Sort; | |||
goodx.status = item.Status==1?0:1; | |||
goodx.url=item.Goods_ImgUrl; | |||
goodx.deviceID = ConfigName.getInstance().DeviceId; | |||
goodx.userID = ConfigName.getInstance().user.userID; | |||
QueryDB.AddGoods(goodx); | |||
} | |||
} | |||
//2.新增物料 | |||
for (BPA_MATERIAL item:QueryDB.GetMaterialALL()) | |||
{ | |||
QueryDB.DeleteMaterial(item); | |||
} | |||
ConcurrentHashMap<String,BPA_MATERIAL> Info=new ConcurrentHashMap<>(); | |||
List<BatchingsInfo> bayc=data.BatchingsInfos; | |||
Collections.sort(bayc, new Comparator<BatchingsInfo>() { | |||
@Override | |||
public int compare(BatchingsInfo o1, BatchingsInfo o2) { | |||
return Double.valueOf(o1.BatchingKey).compareTo(Double.valueOf(o2.BatchingKey)); | |||
} | |||
}); | |||
Integer I=0; | |||
for (BatchingsInfo item:bayc) | |||
{ | |||
BPA_MATERIAL bpa_material=new BPA_MATERIAL(); | |||
bpa_material.id=item.BatchingId; | |||
bpa_material.name=item.BatchingName; | |||
bpa_material.imgUrl=""; | |||
bpa_material.createTime=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(new Date().getTime() + I*1000));; | |||
bpa_material.deviceID= ConfigName.getInstance().DeviceId; | |||
bpa_material.userID=ConfigName.getInstance().user.userID; | |||
if(!Info.containsKey(item.BatchingId)) | |||
Info.put(item.BatchingId,bpa_material); | |||
I++; | |||
} | |||
for (String item:Info.keySet()) | |||
{ | |||
QueryDB.AddMaterial(Info.get(item)); | |||
} | |||
//3.新增商品配方关联表 | |||
for (BPA_SILOSANDMATERIAL item:QueryDB.GetSilosAndMaterialALL())//删除料仓关联物料 | |||
{ | |||
item.materialID=""; | |||
QueryDB.UpdateSilosAndMaterial(item); | |||
} | |||
for (BPA_GOODSRECIPE item:QueryDB.GetGoodsSrecipeALL())//删除商品配方明细 | |||
{ | |||
QueryDB.DeleteGoodsSrecipe(item); | |||
} | |||
ConcurrentHashMap<String,Batchingstechnology> chnology=new ConcurrentHashMap<>(); | |||
for(Batchingstechnology item:data.Batchingstechnologys) | |||
{ | |||
if(!Info.containsKey(item.BomentryId)) | |||
chnology.put(item.BomentryId,item); | |||
} | |||
for(GoodsBom item:data.GoodsBomInfos) | |||
{ | |||
BPA_GOODSRECIPE da=new BPA_GOODSRECIPE(); | |||
da.goodsID = item.GoodsId; | |||
da.exp=item.BomName; | |||
da.materialType = item.IsMain?1:0; | |||
da.deviceID = ConfigName.getInstance().DeviceId; | |||
da.userID = ConfigName.getInstance().user.userID; | |||
for (BatchingsInfo info: data.BatchingsInfos) | |||
{ | |||
if(info.GoodsBomId.equals(item.GoodsBomId)) | |||
{ | |||
da.id=info.Id; | |||
Batchingstechnology gy= chnology.get(info.Id); | |||
da.materialID = info.BatchingId; | |||
da.value = (int)info.BomQty; | |||
if(gy!=null) | |||
{ | |||
da.sort =gy.Sort; | |||
} | |||
QueryDB.AddGoodsSrecipe(da); | |||
} | |||
} | |||
} | |||
} catch (Exception e) { | |||
Log.d("TAG", "RefreshTheData: "); | |||
} | |||
} | |||
//endregion | |||
} |
@@ -6,6 +6,9 @@ import androidx.fragment.app.Fragment; | |||
import androidx.recyclerview.widget.LinearLayoutManager; | |||
import androidx.recyclerview.widget.RecyclerView; | |||
import android.app.Activity; | |||
import android.content.Context; | |||
import android.content.ContextWrapper; | |||
import android.os.Bundle; | |||
import android.view.LayoutInflater; | |||
import android.view.View; | |||
@@ -13,7 +16,10 @@ import android.view.ViewGroup; | |||
import com.example.bpa.R; | |||
import com.example.bpa.config.DataBus; | |||
import com.example.bpa.config.MessageName; | |||
import com.example.bpa.helper.WrapContentLinearLayoutManager; | |||
import com.example.bpa.message.MessageLooper; | |||
import com.example.bpa.message.MessageManager; | |||
import com.example.bpa.view.adapter.maingoods_adapter; | |||
import com.example.bpa.view.adapter.makegood_adapter; | |||
import com.example.bpa.view.control.MyLayoutManager; | |||
@@ -63,8 +69,18 @@ public class HomeFragment extends Fragment implements View.OnClickListener, MyCl | |||
* 初始化按钮事件 | |||
*/ | |||
private void initEvents() { | |||
activity=findActivity(view.getContext()); | |||
} | |||
private Activity findActivity(@NonNull Context context) { | |||
if (context instanceof Activity) { | |||
return (Activity) context; | |||
} else if (context instanceof ContextWrapper) { | |||
return findActivity(((ContextWrapper) context).getBaseContext()); | |||
} else { | |||
return null; | |||
} | |||
} | |||
maingoods_adapter goodadapter; | |||
/** | |||
* 初始化数据加载 | |||
*/ | |||
@@ -75,7 +91,7 @@ public class HomeFragment extends Fragment implements View.OnClickListener, MyCl | |||
layout.setAutoMeasureEnabled(true); | |||
good_recyclerView.setLayoutManager(layout); | |||
maingoods_adapter goodadapter = new maingoods_adapter( getContext()); | |||
goodadapter = new maingoods_adapter( getContext()); | |||
good_recyclerView.setAdapter(goodadapter); | |||
DataBus.getInstance().UpdateMainGoods();//更新商品 | |||
@@ -120,9 +136,21 @@ public class HomeFragment extends Fragment implements View.OnClickListener, MyCl | |||
//endregion | |||
//region 接收事件 | |||
Activity activity=null; | |||
public void RegisterMessage() | |||
{ | |||
MessageManager.getInstance().registerMessageReceiver(this, MessageName.Common.name(), new MessageLooper.OnMessageListener() { | |||
@Override | |||
public void onMessage(Object msg) { | |||
activity.runOnUiThread(new Runnable() { | |||
@Override | |||
public void run() { | |||
DataBus.getInstance().UpdateMainGoods();//更新商品 | |||
goodadapter.notifyDataSetChanged(); | |||
} | |||
}); | |||
} | |||
}); | |||
} | |||
//endregion | |||
} |