fg_yida_2/YiDa_WinForm/Service/YiDaUploadService.cs

365 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using AlibabaCloud.SDK.Dingtalkoauth2_1_0.Models;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Tea;
using YiDa_WinForm.Config;
using YiDa_WinForm.Model;
using YiDa_WinForm.Service.Mqtt;
namespace YiDa_WinForm.Service
{
public class YiDaUploadService
{
private readonly ButtonOperationService _buttonService;
// 数据库连接配置
private readonly string _connectionString = AppConfig.MySqlConnectionString;
// 通知UI层
public event Action<string> MessageReceived;
// 钉钉token
static readonly string _tokenAppKey = AppConfig.YiDaTokenAppKey;
static readonly string _tokenAppSecret = AppConfig.YiDaTokenAppSecret;
// 宜搭上传配置
static readonly string _appType = AppConfig.YiDaAppType;
static readonly string _systemToken = AppConfig.YiDaSystemToken;
static readonly string _userId = AppConfig.YiDaUserId;
static readonly string _formUuid = AppConfig.YiDaFormUuid;
static readonly string _processCode = AppConfig.YiDaProcessCode;
// 报废图片
public string _reformationPicture = null;
/// <summary>
/// 创建 OAuth2 客户端(获取 token 用)
/// </summary>
/// <returns></returns>
private static AlibabaCloud.SDK.Dingtalkoauth2_1_0.Client CreateClient()
{
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config();
config.Protocol = "https";
config.RegionId = "central";
return new AlibabaCloud.SDK.Dingtalkoauth2_1_0.Client(config);
}
/// <summary>
/// 获取钉钉 AccessToken
/// </summary>
/// <returns>AccessToken 字符串</returns>
public string GetDingDingToken()
{
string strToken = string.Empty;
GetAccessTokenResponse token = null;
var client = CreateClient();
var getAccessTokenRequest = new GetAccessTokenRequest
{
AppKey = _tokenAppKey,
AppSecret = _tokenAppSecret,
};
try
{
token = client.GetAccessToken(getAccessTokenRequest);
}
catch (TeaException err)
{
string errorMsg = $"获取钉钉Token异常【TeaException】错误码={err.Code},错误信息={err.Message}";
Console.WriteLine(errorMsg);
}
catch (Exception ex)
{
string errorMsg = $"获取 token 异常:{ex.Message}";
Console.WriteLine(errorMsg);
}
return token != null ? token.Body.AccessToken : string.Empty;
}
//加上逻辑判断的上传
//记载宜搭上传成功日志
private static async Task RecordSuccessLog(List<MqttModel> mqttLists)
{
if (mqttLists != null && mqttLists.Count > 0)
{
var buttonService = new ButtonOperationService();
await buttonService.CreateSuccessLog(mqttLists);
}
}
//新版宜搭API
private static AlibabaCloud.SDK.Dingtalkyida_2_0.Client CreateYiDaClient()
{
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config();
config.Protocol = "https";
config.RegionId = "central";
return new AlibabaCloud.SDK.Dingtalkyida_2_0.Client(config);
}
public async Task UploadDatabaseDataToYiDaWithLogging(string accessToken, List<YiDaModel> yidaLists,
List<MqttModel> mqttLists, MainForm form)
{
var client = CreateYiDaClient();
AlibabaCloud.SDK.Dingtalkyida_2_0.Models.StartInstanceHeaders startInstanceHeaders =
new AlibabaCloud.SDK.Dingtalkyida_2_0.Models.StartInstanceHeaders();
startInstanceHeaders.XAcsDingtalkAccessToken = accessToken;
for (int i = 0; i < yidaLists.Count; i++)
{
var item = yidaLists[i];
var mqttItem = mqttLists[i];
var dataDict = new Dictionary<string, object>
{
//左侧为宜搭表中字段唯一标识值,右侧为要传递给宜搭的值。
{ "textField_mha98neu", item.textField_mha98neu }, //供应商代码
{ "textField_mha98nev", item.textField_mha98nev }, //供应商名称
{ "textField_mha98new", item.textField_mha98new }, //车型
{ "textField_mha98nex", item.textField_mha98nex }, //零件号
{ "textField_mha98ney", item.textField_mha98ney }, //零件名称
{ "textField_mha98nf1", item.textField_mha98nf1 }, //参数名
{ "textField_mhx44i2i", item.textField_mhx44i2i }, //参数值
{ "textField_mhx44i2j", item.textField_mhx44i2j }, //下公差
{ "textField_mhx44i2k", item.textField_mhx44i2k }, //上公差
{ "textField_mha98nf7", item.textField_mha98nf7 }, //零件责任人
{ "textField_mhlvt8ht", DateTime.Now.ToString("yyyy-MM-dd") }, //写入时间
{ "textField_mha98nf5", item.textField_mha98nf5 }, //合格判断
{ "textField_mha98nf0", item.textField_mha98nf0 }, //工位
{ "textField_mha98nfh", item.textField_mha98nfh } //外保负责人
};
string jsonData = JsonConvert.SerializeObject(dataDict);
AlibabaCloud.SDK.Dingtalkyida_2_0.Models.StartInstanceRequest startInstanceRequest =
new AlibabaCloud.SDK.Dingtalkyida_2_0.Models.StartInstanceRequest
{
AppType = _appType,
SystemToken = _systemToken,
UserId = _userId,
Language = "zh_CN",
FormUuid = _formUuid,
FormDataJson = jsonData,
ProcessCode = _processCode,
};
try
{
var response = client.StartInstanceWithOptions(startInstanceRequest, startInstanceHeaders,
new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
if (response != null && response.Body != null)
{
// 上传成功就存入 MySQL
await RecordSuccessLog(mqttLists);
string logData = JsonConvert.SerializeObject(dataDict, Formatting.Indented);
form.AppendLog($"上传数据成功:\r\n{logData}");
Console.WriteLine($"上传数据成功:\r\n{logData}");
}
else
{
Console.WriteLine($"上传返回空结果,数据未存入 MySQL。");
string logData = JsonConvert.SerializeObject(dataDict, Formatting.Indented);
form.AppendLog($"上传返回空结果,数据未存入 MySQL:\r\n{logData}");
}
}
catch (TeaException err)
{
Console.WriteLine($"上传异常:{err.Code} --- {err.Message}");
string logData = JsonConvert.SerializeObject(dataDict, Formatting.Indented);
form.AppendLog($"上传异常:{err.Code} --- {err.Message}\r\n数据:\r\n{logData}");
}
catch (Exception ex)
{
Console.WriteLine($"上传异常:{ex.Message}");
string logData = JsonConvert.SerializeObject(dataDict, Formatting.Indented);
form.AppendLog($"上传异常:{ex.Message}\r\n数据:\r\n{logData}");
}
}
}
/// <summary>
/// 计算钉钉加签
/// </summary>
/// <param name="timestamp"></param>
/// <param name="secret"></param>
/// <returns></returns>
static string CalcSign(long timestamp, string secret)
{
string stringToSign = $"{timestamp}\n{secret}";
var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
return Convert.ToBase64String(hashBytes);
}
/// <summary>
/// 图片上传至钉钉群
/// </summary>
/// <param name="token"></param>
/// <param name="filePath"></param>
public async Task UploadScrapCertificate(string token, string filePath)
{
//string chatId = "chatxxxxxxxx";
//long fileLen = new FileInfo(filePath).Length;
// 1. 初始化
HttpClient client = new HttpClient
{
BaseAddress = new Uri("https://oapi.dingtalk.com")
};
var form = new MultipartFormDataContent();
var fileStream = File.OpenRead(filePath);
var streamContent = new StreamContent(fileStream);
streamContent.Headers.ContentType =
new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg"); // 或 image/png
form.Add(streamContent, "media", Path.GetFileName(filePath));
form.Add(new StringContent("image"), "type"); // 接口要求字段 type=image
// 2. 发送请求上传文件access_token 放查询串)
var url = $"/media/upload?access_token={token}";
var resp = await client.PostAsync(url, form);
resp.EnsureSuccessStatusCode();
string json = await resp.Content.ReadAsStringAsync();
JObject jo = JObject.Parse(json);
string mediaId = jo["media_id"].Value<string>();
MergeAndSaveData(mediaId);
Console.WriteLine($"上传完成mediaId = {mediaId}");
// 3. 发送群消息
var webhook =
"https://oapi.dingtalk.com/robot/send?access_token=4dc45fc8b61d58f49b7c55c5941aab485d5d07b88ce68cf4e1b8518ac79419f2";
string secret = "SEC5462c700f1b98570014e584e3e304eee2e6e1df9aa2e6d1c529337437559f301"; // 机器人详情页复制
long ts = DateTimeOffset.Now.ToUnixTimeMilliseconds();
string ymdhms = DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss");
string sign = CalcSign(ts, secret); // HMACSHA256→Base64
string webhook_url = $"{webhook}&timestamp={ts}&sign={sign}";
//var msg = new
//{
// msgtype = "text",
// text = new { content = $"报废凭证拍照({ymdhms}" }
//};
var msg = new
{
msgtype = "markdown",
markdown = new
{
title = "报废证据上传",
text = $"## 报废凭证照片\n<img src=\"{mediaId}\" width=\"200\" />\n\n> 时间:{ymdhms}"
}
};
string transJson = JsonConvert.SerializeObject(msg);
var resp2 = await client.PostAsync(webhook_url,
new StringContent(transJson, Encoding.UTF8, "application/json"));
resp2.EnsureSuccessStatusCode();
//var msg3 = new
//{
// msgtype = "image",
// image = new { picURL = $"{mediaId}" }
//};
//string transJson3 = JsonConvert.SerializeObject(msg3);
//var resp3 = await client.PostAsync(webhook_url, new StringContent(transJson3, Encoding.UTF8, "application/json"));
//resp3.EnsureSuccessStatusCode();
string json2 = await resp2.Content.ReadAsStringAsync();
JObject res2 = JObject.Parse(json2);
string errmsg = res2["errmsg"].Value<string>();
Console.WriteLine($"发送群消息完成msg = {errmsg}");
}
private async Task MergeAndSaveData(string mediaId)
{
try
{
// 读取最新注塑机数据的receive_dataJSON字符串
string latestReceiveData = null;
long latestId = 0; // 用主键ID定位最新数据避免time类型问题
using (var conn = new MySqlConnection(_connectionString))
{
await conn.OpenAsync();
// 查询最新注塑机数据device1/2
string getLatestSql = @"SELECT id, receive_data FROM yida_mqtt_message
WHERE device_code IN ('device1','device2')
ORDER BY id DESC LIMIT 1";
using (var cmd = new MySqlCommand(getLatestSql, conn))
{
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
latestId = reader.GetInt64(0);
latestReceiveData = reader.IsDBNull(1) ? null : reader.GetString(1);
}
}
}
// 无注塑机数据时直接返回
if (string.IsNullOrEmpty(latestReceiveData))
{
MessageReceived?.Invoke("数据库中无注塑机数据,无法合并");
return;
}
// 反序列化注塑机JSON数据
var dataModel = JsonConvert.DeserializeObject<SQLDataModel>(latestReceiveData);
if (dataModel == null || dataModel.@params == null)
{
dataModel = new SQLDataModel
{
time = DateTime.Now.Millisecond,
@params = new SQLParamModel()
};
}
dataModel.@params.BU = mediaId;
_reformationPicture = mediaId;
// 重新序列化为JSON
string mergedData = JsonConvert.SerializeObject(dataModel);
// 更新数据库用ID定位避免time类型问题
string updateSql = @"UPDATE yida_mqtt_message
SET receive_data = @mergedData
WHERE id = @latestId";
using (var updateCmd = new MySqlCommand(updateSql, conn))
{
updateCmd.Parameters.AddWithValue("@mergedData", mergedData);
updateCmd.Parameters.AddWithValue("@latestId", latestId);
int affectedRows = await updateCmd.ExecuteNonQueryAsync();
if (affectedRows > 0)
{
MessageReceived?.Invoke($"成功合并BU字段{mediaId}更新ID={latestId}");
}
else
{
MessageReceived?.Invoke("更新失败:未找到匹配的注塑机数据");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
}