123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- package com.dashitech.callcenter.socket;
- import com.dashitech.businessdata.dao.*;
- import com.dashitech.businessdata.entity.CallLogEntity;
- import com.dashitech.businessdata.entity.CallRecordEntity;
- import com.dashitech.businessdata.entity.HospitalConfig;
- import com.dashitech.callcenter.webSocket.service.PhoneWebSocket;
- import com.dashitech.utils.DateUtil2;
- import com.dashitech.utils.JsonUtil;
- import com.dashitech.utils.PropertiesUtil;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import net.sf.json.JSONObject;
- import org.apache.commons.lang.StringUtils;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.net.Socket;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.*;
- /**
- * Created by chi on 2020/8/6.
- */
- @Service
- public class HandlerThread {
- private static Log log = LogFactory.getLog(HandlerThread.class);
- // 这里使用静态,让 service 属于类
- private static ICallLogDAO callLogDAO;
- private static ICallRecordDAO callRecordDAO;
- @Autowired
- public void setCallRecordDAO(ICallRecordDAO callRecordDAO) {
- HandlerThread.callRecordDAO = callRecordDAO;
- }
- @Autowired
- public void setCallLogDAO(ICallLogDAO callLogDAO) {
- HandlerThread.callLogDAO = callLogDAO;
- }
- private static IDictionaryDAO dictionaryDAO;
- @Autowired
- public void setDictionaryDAO(IDictionaryDAO dictionaryDAO) {
- HandlerThread.dictionaryDAO = dictionaryDAO;
- }
- private static IDepartmentDAO departmentDAO;
- @Autowired
- public void setDepartmentDAO(IDepartmentDAO departmentDAO) {
- HandlerThread.departmentDAO = departmentDAO;
- }
- private static IHospitalConfigDAO hospitalConfigDAO;
- @Autowired
- public void setHospitalConfigDAO(IHospitalConfigDAO hospitalConfigDAO) {
- HandlerThread.hospitalConfigDAO = hospitalConfigDAO;
- }
- private static String project;
- private static String recordNginxPath;
- private static String recordRegex;
- private Socket sc;
- private static Map<String,String> phoneMap = new HashMap<>();
- private static Map<String,CallLogEntity> phoneLog = new HashMap<>();
- private String his = "";
- public HandlerThread() {
- }
- public HandlerThread(Socket client) {
- sc = client;
- }
- public void run() {
- DataInputStream input = null;
- DataOutputStream output = null;
- try {
- // sc.setSoTimeout(10000);
- input = new DataInputStream(sc.getInputStream());
- output = new DataOutputStream(sc.getOutputStream());
- String reset = "";
- //持续读取内部消息
- while (true) {
- // System.out.println("处理客户端数据:"+input.readUTF());
- // System.out.println("3333333333333333333333");
- //获取信息流长度
- byte[] b = new byte[4];
- reset = "keepalive";
- input.read(b);
- int count = bytes2Int(b);
- // System.out.println("count::"+count);
- //根据信息流长度获取信息流
- byte[] b1 = new byte[count];
- input.read(b1);
- //将信息流转换为String
- String data = new String(b1);
- System.out.println("data:"+data+"his"+his);
- if(project == null) {
- project = PropertiesUtil.getProperty("project");
- recordNginxPath = PropertiesUtil.getProperty("db.hjzx.record.nginx");
- recordRegex = PropertiesUtil.getProperty("db.hjzx.record.path.regex");
- }
- if (data != null || !data.equals("")&&data.substring(0,1).equals("{")) {
- if (JsonUtil.toJSONObject(data).containsKey("channelStatusList")){
- List llist = JsonUtil.toJSONObject(data).optJSONArray("channelStatusList");
- JSONObject jsonObject = JsonUtil.toJSONObject(llist.get(0).toString());
- sendSocket(jsonObject,his);
- handleCallLog(jsonObject,his);
- reset = "channelstatus";
- }else if(JsonUtil.toJSONObject(data).containsKey("recordList")){
- saveCallLog(data,his);
- reset = "addrec";
- }
- }
- if (data != null && data.length() >= 10){
- String dataStr = "";
- if (reset.equals("addrec")){
- dataStr = "{\"cmd\":\""+reset+"\",\"error\":\"0\", \"timestamp\":\""+(System.currentTimeMillis() / 1000)+"\"}";
- }else{
- dataStr = "{\"cmd\":\""+reset+"\", \"timestamp\":\""+(System.currentTimeMillis() / 1000)+"\"}";
- }
- if (data.indexOf("loginreq") >= 0){
- //{"cmd":"loginreq","ipaddr":"192.168.25.37","serialNo":"21380501019804","recordNumber":4,"webport":80,"filestoretype":0}his
- if(JsonUtil.toJSONObject(data).containsKey("serialNo")){
- his = JsonUtil.toJSONObject(data).getString("serialNo");
- }else{
- his = JsonUtil.toJSONObject(data).getString("sernelNo");
- }
- // 设备 21040501017523 写死支持 院区1
- if(his.equals("21040501017523")){
- his = "1";
- }else{
- his = callLogDAO.selectSernelNo("sernelNo",his);
- }
- dataStr = "{\"cmd\":\"loginres\", \"error\":\"0\", \"timestamp\":\"" + (System.currentTimeMillis() / 1000) + "\"}";
- }
- System.out.println("redate>>"+dataStr+"his"+his);
- output.write(dataToBytes(dataStr));
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("服务器EOFException异常");
- } finally {
- if (output != null) {
- try {
- output.close();
- } catch (Exception e) {
- output = null;
- }
- }
- if (input != null) {
- try {
- input.close();
- } catch (Exception e) {
- input = null;
- }
- }
- if (sc != null) {
- try {
- sc.close();
- } catch (Exception e) {
- sc = null;
- }
- }
- }
- }
- /**
- * 将发送内容转换为byte数组
- * 需要注意:byte前面四位需要描述整个发送内容的长度(dataStr)
- *
- * @param dataStr
- */
- public byte[] dataToBytes(String dataStr) {
- //将int转换为byte数组
- byte[] lengthBytes = int2Bytes(dataStr.length());
- //将string转换为byte数组
- byte[] dataBytes = dataStr.getBytes();
- //最终发送的byte数组,int byte数组长度和string byte数组长度相加得到最终长度
- byte[] lengthAndDataBytes = new byte[(lengthBytes.length + dataBytes.length)];
- //将int byte数组四位加入到新byte数组中
- lengthAndDataBytes[0] = lengthBytes[0];
- lengthAndDataBytes[1] = lengthBytes[1];
- lengthAndDataBytes[2] = lengthBytes[2];
- lengthAndDataBytes[3] = lengthBytes[3];
- //将string byte数组四位加入到新byte数组中
- for (int index = 4; index < lengthAndDataBytes.length; index++) {
- lengthAndDataBytes[index] = dataBytes[index - 4];
- }
- return lengthAndDataBytes;
- }
- /**
- * byte数组转换为int
- *
- * @param bytes
- * @return
- */
- public static int bytes2Int(byte[] bytes) {
- //如果不与0xff进行按位与操作,转换结果将出错,有兴趣的同学可以试一下。
- int int1 = bytes[0] & 0xff;
- int int2 = (bytes[1] & 0xff) << 8;
- int int3 = (bytes[2] & 0xff) << 16;
- int int4 = (bytes[3] & 0xff) << 24;
- return int1 | int2 | int3 | int4;
- }
- /**
- * int 转换为 byte数组
- *
- * @param integer
- * @return
- */
- public static byte[] int2Bytes(int integer) {
- byte[] bytes = new byte[4];
- bytes[3] = (byte) ((byte) integer >> 24);
- bytes[2] = (byte) ((byte) integer >> 16);
- bytes[1] = (byte) ((byte) integer >> 8);
- bytes[0] = (byte) integer;
- return bytes;
- }
- /**
- * 发送弹屏socket,将电话号码返回过去
- * 201为通话中
- * 202为振铃
- *
- */
- public void sendSocket(JSONObject jsonObject,String his) {
- try {
- putPhoneMap("phone_num_port",his);
- if (jsonObject != null && jsonObject.containsKey("calldirection") && jsonObject.get("calldirection").toString().equals("1") || jsonObject.get("calldirection").toString() == "1") {
- if (jsonObject.containsKey("phonestate") && jsonObject.get("phonestate").toString().equals("3") || jsonObject.get("phonestate").toString() == "3") {
- if (jsonObject.containsKey("channel")&&jsonObject.get("channel").toString()!=null) {
- Map rMap = new HashMap();
- //TODO 增加返回 uuid 并且保存通话记录数据
- if (jsonObject.containsKey("dtmfa") && jsonObject.get("dtmfa").toString() != null && !jsonObject.optString("dtmfa").toString().equals("")){
- rMap.put("phone", jsonObject.opt("dtmfa"));
- rMap.put("status", 201);
- //TODO 先保存通话记录
- CallLogEntity callLogEntity = new CallLogEntity();
- callLogEntity.setdTMFA(jsonObject.optString("dtmfa"));
- callLogEntity.setdTMFB(jsonObject.optString("dtmfb"));
- if(StringUtils.isNotEmpty(jsonObject.optString("rstime"))) {
- callLogEntity.setResponseTime(DateUtil2.parseDateTime(jsonObject.optString("rstime")));
- }
- saveItsmCallRecord(callLogEntity,jsonObject.optString("uuid"));
- rMap.put("callId",jsonObject.optString("uuid"));
- }else {
- rMap.put("phone","");
- rMap.put("status", 201);
- }
- ObjectMapper objectMapper = new ObjectMapper();
- String json = objectMapper.writeValueAsString(rMap);
- PhoneWebSocket.sendMessage(phoneMap.get(his+jsonObject.get("channel").toString()),json);
- }
- } else if (jsonObject.containsKey("phonestate") && jsonObject.get("phonestate").toString().equals("4") || jsonObject.get("phonestate").toString() == "4") {
- Map rMap = new HashMap();
- rMap.put("msg","来电话啦!" );
- rMap.put("status", 202);
- ObjectMapper objectMapper = new ObjectMapper();
- String json = objectMapper.writeValueAsString(rMap);
- if (jsonObject.containsKey("channel")&&jsonObject.get("channel").toString()!=null){
- PhoneWebSocket.sendMessage(phoneMap.get(his+jsonObject.get("channel").toString()),json);
- }
- CallLogEntity callLog = new CallLogEntity();
- callLog.setCallState(0);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private void handleCallLog(JSONObject jsonObject,String his){
- if(jsonObject.get("phonestate").toString().equals("4")){
- // 主叫号码不等于空字符串,并且不等于座机号(通道号获得),即可判断为来电号码
- if(!jsonObject.get("dtmfa").toString().equals("") && !jsonObject.get("dtmfa").toString().equals(phoneMap.get(his+jsonObject.get("channel").toString()))){
- phoneLog.put(his+jsonObject.get("channel").toString(),getCallLog(jsonObject));
- }
- //如果phonestate 为零则表示话机为空闲状态,则保存通话记录
- }else if(jsonObject.get("phonestate").toString().equals("0")){
- CallLogEntity callLog = phoneLog.get(his+jsonObject.get("channel").toString());
- if (callLog!=null){
- if (jsonObject.containsKey("dtmfa")&& StringUtils.isNotEmpty(jsonObject.get("dtmfa").toString())&&!jsonObject.get("dtmfa").toString().equals("")&&!jsonObject.get("dtmfa").toString().equals(" ")){
- // 查询科室信息 并赋值
- callLog.setCallDept(getDeptByDTMFA(jsonObject.get("dtmfa").toString()));
- }else {
- callLog.setCallDept("暂无");
- }
- callLog.setHosId(Integer.parseInt(his));
- callLogDAO.save(callLog);
- }
- }else if(jsonObject.get("phonestate").toString().equals("1")){
- phoneLog.put(his+jsonObject.get("channel").toString(),null);
- }else if(jsonObject.get("phonestate").toString().equals("3")){
- phoneLog.put(his+jsonObject.get("channel").toString(),null);
- }
- }
- /**
- * 将json转换为实体
- * 默认 已接未接为 未接
- * 默认 通话类型为 呼入
- * 默认 时间为 当前时间。
- * @param jsonObject
- * @return
- */
- private CallLogEntity getCallLog(JSONObject jsonObject){
- CallLogEntity callLog = new CallLogEntity();
- if (jsonObject.containsKey("channel")){
- callLog.setPhyIDA(jsonObject.get("channel").toString());
- }
- if (jsonObject.containsKey("dtmfa")) {
- callLog.setdTMFA(jsonObject.get("dtmfa").toString());
- callLog.setCallDept(getDeptByDTMFA(jsonObject.get("dtmfa").toString()));
- }
- if (jsonObject.containsKey("dtmfb")){
- callLog.setdTMFB(jsonObject.get("dtmfb").toString());
- }
- callLog.setResponseTime(new Date());
- callLog.setCallState(0);
- callLog.setCallType(1);
- return callLog;
- }
- public void putPhoneMap(String key,String his){
- // List<DictionaryEntity> dictionaryEntityList = dictionaryDAO.selectDictionaryByKey(key);
- List<HospitalConfig> hospitalConfigList = hospitalConfigDAO.getHospitalConfigList(key,his);
- if (hospitalConfigList!=null&&hospitalConfigList.size()>0){
- for (HospitalConfig hospitalConfig:hospitalConfigList){
- phoneMap.put(his+hospitalConfig.getValue2(),hospitalConfig.getValue());
- }
- }
- }
- /**
- * 保存通话记录
- * @param message
- */
- public void saveCallLog(String message,String his){
- //TODO 修改通话记录数据;DTMFA DTMFB rstime
- if (JsonUtil.toJSONObject(message).containsKey("recordList")) {
- List list = JsonUtil.toJSONObject(message).optJSONArray("recordList");
- if (list!=null&&list.size()>0){
- JSONObject jsonObject = JsonUtil.toJSONObject(list.get(0).toString());
- CallLogEntity callLog = new CallLogEntity();
- if (jsonObject.containsKey("phyIDA")){
- callLog.setPhyIDA(jsonObject.get("phyIDA").toString());
- }
- if (jsonObject.containsKey("DTMFA")){
- callLog.setdTMFA(jsonObject.get("DTMFA").toString());
- callLog.setCallDept(getDeptByDTMFA(jsonObject.get("DTMFA").toString()));
- }
- if (jsonObject.containsKey("DTMFB")){
- callLog.setdTMFB(jsonObject.get("DTMFB").toString());
- }
- if (jsonObject.containsKey("rstime")){
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- try {
- callLog.setResponseTime(sdf.parse(jsonObject.get("rstime").toString()));
- } catch (ParseException e) {
- e.printStackTrace();
- }
- }
- if (jsonObject.containsKey("longtime")){
- callLog.setLongTime(jsonObject.get("longtime").toString());
- }
- if (jsonObject.containsKey("path")){
- callLog.setPath(jsonObject.get("path").toString());
- }
- if(callLog.getPhyIDA() != null){
- // 判断为呼出(主叫号码等于分机号(通道号)为呼出)
- if(callLog.getdTMFA() != null &&phoneMap!=null&&phoneMap.size()>0&& phoneMap.get(his+callLog.getPhyIDA()).equals(callLog.getdTMFA())){
- callLog.setCallType(0);
- // callLog.setCallState(1);
- // 判断为呼入(被叫号码等于分机号(通道号)为呼入)
- }else if(callLog.getdTMFB()!= null &&phoneMap!=null&&phoneMap.size()>0&& phoneMap.get(his+callLog.getPhyIDA()).equals(callLog.getdTMFB())){
- callLog.setCallType(1);
- // callLog.setCallState(1);
- }else{//未知
- callLog.setCallType(2);
- }
- callLog.setCallState(1);
- }
- callLog.setHosId(Integer.parseInt(his));
- callLogDAO.save(callLog);
- //TODO 根据配置文件开关,是否保存到ITSM的通话记录数据
- saveItsmCallRecord(callLog,null);
- }
- }
- }
- private String getDeptByDTMFA(String phone){
- try {
- if (phone!=null){
- phone = phone.trim();
- if (phone.equals("")){
- return "暂无";
- }
- //给来电科室赋值
- String deptName = departmentDAO.getDeptNameByPhone(phone);
- if (deptName!=null&&!deptName.equals("")){
- return deptName;
- }else {
- /* String deptName2 = departmentDAO.getDeptNameByWorkOrderPhone(phone);
- if (deptName2!=null&&!deptName2.equals("")){
- return deptName2;
- }else {
- return "暂无";
- }*/
- return "暂无";
- }
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- return "暂无";
- }
- /**
- * 根据配置文件开关,是否保存到ITSM的通话记录数据
- */
- private void saveItsmCallRecord(CallLogEntity callLog,String uuid) {
- try {
- if("ITSM".equals(project)) {
- CallRecordEntity recordEntity = null;
- log.info("开始保存通话记录");
- //TODO 根据uuid区分是:新增通话记录,还是修改附件的通话记录
- if(StringUtils.isNotEmpty(uuid)) { //新增
- Long id = callRecordDAO.selectIdByUuid(uuid);
- if(id == null) {
- recordEntity = new CallRecordEntity();
- recordEntity.setVersion(0);
- recordEntity.setCallAccept(uuid);
- recordEntity.setCallerIdNumber(callLog.getdTMFA());
- recordEntity.setDestinationNumber(callLog.getdTMFB());
- recordEntity.setCreatedTime(callLog.getResponseTime());
- callRecordDAO.save(recordEntity);
- log.info("新增临时通话记录完成");
- }else {
- log.info("已有临时通话记录,忽略此条uuid:"+uuid);
- }
- }else { //修改
- log.info("开始匹配临时通话记录");
- recordEntity = callRecordDAO.selectByParams(callLog.getdTMFA(), callLog.getdTMFB(), callLog.getResponseTime());
- //TODO 根据【主叫、被叫、起始时间】判断是否查询到对应数据,来绑定附件,如果未匹配到,直接新增
- String newUUID = null;
- if(recordEntity != null) {
- log.info("匹配到临时通话记录!开始修改");
- newUUID = recordEntity.getCallAccept();
- }else {
- log.info("未匹配到临时通话记录!开始新增");
- recordEntity = new CallRecordEntity();
- newUUID = UUID.randomUUID().toString();
- }
- recordEntity.setCallAccept(newUUID);
- recordEntity.setVersion(0);
- recordEntity.setCallerIdNumber(callLog.getdTMFA());
- recordEntity.setDestinationNumber(callLog.getdTMFB());
- recordEntity.setCreatedTime(callLog.getResponseTime());
- recordEntity.setCallTime(callLog.getLongTime());
- recordEntity.setRecordingFileName(callLog.getPath());
- recordEntity.setIsAnswered(callLog.getCallState());
- //处理结束时间
- if(callLog.getResponseTime() != null && callLog.getLongTime() != null) {
- Date overTime = DateUtil2.addSeconds(callLog.getResponseTime(), Integer.valueOf(callLog.getLongTime()));
- recordEntity.setOverTime(overTime);
- }
- //院区
- if(callLog.getHosId() != null) {
- recordEntity.setBranch(callLog.getHosId().longValue());
- }
- //呼入呼出,其它
- if(callLog.getCallType() != null) {
- if("1".equals(callLog.getCallType().toString())) {
- recordEntity.setCallType("2");
- }else if("2".equals(callLog.getCallType().toString())) {
- recordEntity.setCallType("1");
- }else {
- recordEntity.setCallType("3");
- }
- }
- //处理录音地址
- if(callLog.getPath() != null) {
- String newPath = callLog.getPath();
- String[] arr = callLog.getPath().split(recordRegex);
- if (arr.length > 1) {
- newPath = recordNginxPath + arr[1];
- }
- recordEntity.setRecordingFileName(newPath);
- }
- callRecordDAO.save(recordEntity);
- log.info("附件通话记录保存完成");
- }
- log.info("ITSM保存通话记录完成:"+recordEntity.getCallAccept());
- System.out.println("ITSM保存通话记录完成:"+recordEntity.getCallAccept());
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- public static void main(String[] args) {
- System.out.println(System.currentTimeMillis() / 1000);
- }
- }
|