package com.sp_comm; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.UnsupportedCommOperationException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Date; import java.util.Enumeration; import javax.swing.JComboBox; import javax.swing.JOptionPane; import javax.swing.JTextField; import com.ComFn; import com.PlaySound; import com.aes.Ecb_Aes; import com.dev.fbs9100.FBS9100_CapState; import com.dev.fbs9100.FBS9100_ChargeState; import com.dev.fbs9100.FBS9100_Cmd; import com.dev.fbs9100.FBS9100_ComBase; import com.dev.fbs9100.FBS9100_ComBuf; import com.dev.fbs9100.FBS9100_DFU; import com.dev.fbs9100.FBS9100_ParamBatt; import com.dev.fbs9100.FBS9100_ParamCharge; import com.dev.fbs9100.FBS9100_ParamDischarge; import com.dev.fbs9100.FBS9100_ParamSystem; import com.dev.fbs9100.FBS9100_ResCapData; import com.dev.fbs9100.FBS9100_ResState; import com.dev.fbs9100.FBS9100_VCData; public class SPCommFBS9100 implements Runnable/*, SerialPortEventListener*/ { public static final short CMD_TYPE_READ = 0x03; public static final short CMD_TYPE_WRITE = 0x05; public static final short CMD_TYPE_WRITE_MULTY = 0x10; public static final int DEV_PARAM_DATA_STATE_NULL = 0; public static final int DEV_PARAM_DATA_STATE_QUERY = 1; public static final int DEV_PARAM_DATA_STATE_UPDATE = 2; /*********************************************************************/ final public static String[] ZDHJ_OP_REST_INF_TEXT = new String[] { "ÎÞ²Ù×÷", }; // ¼ì²âϵͳÖпÉÓõÄͨѶ¶Ë¿ÚÀà private static CommPortIdentifier portId; private static Enumeration portList; // ÊäÈëÊä³öÁ÷ public static InputStream inputStream; public static OutputStream outputStream; // RS-232µÄ´®ÐÐ¿Ú public static SerialPort serialPort; private boolean CommThreadRunning = false; private boolean dt_dfu_en = false; private String dt_dfuFileName = ""; Ecb_Aes my_aes = new Ecb_Aes(); private ByteBuffer CommRxBuffer = ByteBuffer.allocate(1500); private ByteBuffer CommTxBuffer = ByteBuffer.allocate(1048); private ByteBuffer DFUCommRxBuffer = ByteBuffer.allocate(1048); private ByteBuffer DFUCommTxBuffer = ByteBuffer.allocate(1048); private FBS9100_DFU m_FBS9100_DFU = new FBS9100_DFU(); private ByteBuffer FBS9100TxBuffer = ByteBuffer.allocate(1048); private ByteBuffer FBS9100RxBuffer = ByteBuffer.allocate(1500); public short comm_tx_cnt = 0; public short comm_rx_cnt = 0; private int comm_bautrate = 9600; public int dt_target_addr = 0; //--------------------------------------------------------// public int dev_param_data_state = 0; public int dev_param_addr = 0; public int[] dev_param_ch_mon_cnt = new int[5]; public int dev_param_curr_range = 0; public double dev_param_wenbo_curr_lev = 0; public int dev_param_auto_restest_interval = 0; public int dev_param_res_test_type = 0; //--------------------------------------------------------// public double dev_stat_version = 0; public int dev_stat_state = 0; public double GroupVol = 0; public double BattCurr = 0; public int BattCurrDir = 0; public double AvgWenBoCurr = 0; public double PeakWenBoCurr = 0; //--------------------------------------------------------// private JTextField dt_show_msg = new JTextField(); private int dt_cmd = FBS9100_ComBase.CMD_GetVIData; private ByteBuffer dt_datatofbs9100 = ByteBuffer.allocate(0); public int dt_cmd_ack = 0; public Date dt_cmd_ack_time = new Date(); //--------------------------------------------------------// //--------------------------------------------------------// public FBS9100_Cmd m_FBS_Cmd = new FBS9100_Cmd(); public FBS9100_VCData m_FBS_VCData = new FBS9100_VCData(); public FBS9100_ParamBatt m_FBS_BattParam = new FBS9100_ParamBatt(); public FBS9100_ParamSystem m_FBS_SystemParam = new FBS9100_ParamSystem(); public FBS9100_ParamDischarge m_FBS_DiscParam = null; public FBS9100_ParamDischarge m_FBS_DiscParamFromDev = null; public FBS9100_ParamCharge m_FBS_ChargeParam = new FBS9100_ParamCharge(); public FBS9100_ResState m_ResTestState = new FBS9100_ResState(); public FBS9100_CapState m_CapTestState = new FBS9100_CapState(); public FBS9100_ChargeState m_ChrTestState = new FBS9100_ChargeState(); public FBS9100_ResCapData m_FBS_ResCapData = new FBS9100_ResCapData(); public ByteBuffer m_TaskList = ByteBuffer.allocate(1024); //--------------------------------------------------------// //--------------------------------------------------------// public SPCommFBS9100(short addr_t, int bitrate) { dt_target_addr = addr_t & 0x00FF; comm_bautrate = bitrate; } public static void searchCommPort(JComboBox cb_comm) { cb_comm.removeAllItems(); @SuppressWarnings("unchecked") Enumeration pl = CommPortIdentifier.getPortIdentifiers(); while (pl.hasMoreElements()) { CommPortIdentifier port_id = pl.nextElement(); if (port_id.getPortType() == CommPortIdentifier.PORT_SERIAL) { cb_comm.addItem(port_id.getName()); } } } public void setCommBautrate(int bt_rate) { try { comm_bautrate = bt_rate; serialPort.setSerialPortParams(comm_bautrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,SerialPort.PARITY_NONE); } catch (UnsupportedCommOperationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //³õʼ»¯´®¿Ú @SuppressWarnings("unchecked") public boolean OpenCommPort(String comm_name) { portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { portId = portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { if (portId.getName().equals(comm_name)) { try { serialPort = (SerialPort) portId.open("SerialPort-Test", 2000); //serialPort.addEventListener(new SPComm()); serialPort.notifyOnDataAvailable(true); /* ÉèÖô®¿ÚͨѶ²ÎÊý */ serialPort.setSerialPortParams(comm_bautrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,SerialPort.PARITY_NONE); outputStream = serialPort.getOutputStream(); inputStream = serialPort.getInputStream(); } catch (PortInUseException e) { e.printStackTrace(); }/* catch (TooManyListenersException e) { e.printStackTrace(); }*/catch (UnsupportedCommOperationException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } } if(null == serialPort) { System.out.println(comm_name + "²»´æÔÚ»òÕýÔÚʹÓÃÖÐ!"); return false; } else { CommTxBuffer.order(ByteOrder.BIG_ENDIAN); CommRxBuffer.order(ByteOrder.BIG_ENDIAN); DFUCommTxBuffer.order(ByteOrder.LITTLE_ENDIAN); DFUCommRxBuffer.order(ByteOrder.LITTLE_ENDIAN); FBS9100TxBuffer.order(ByteOrder.LITTLE_ENDIAN); FBS9100RxBuffer.order(ByteOrder.LITTLE_ENDIAN); comm_tx_cnt = 0; comm_rx_cnt = 0; CommThreadRunning = true; return true; } } private byte[] makeCommTxData() { ByteBuffer buf_t = FBS9100_ComBuf.makeFbs9100CommBuf(255, dt_cmd, dt_datatofbs9100); if(FBS9100_ComBase.CMD_GetVIData != dt_cmd) { dt_cmd = FBS9100_ComBase.CMD_GetVIData; dt_datatofbs9100 = ByteBuffer.allocate(0); } byte[] plain_tx_t = new byte[buf_t.limit()]; byte[] cipher_tx_t = new byte[buf_t.limit()]; buf_t.get(plain_tx_t); my_aes.ecb_encrypt(plain_tx_t, cipher_tx_t, plain_tx_t.length); //System.out.println(ComFn.bytesToHexString(plain_tx_t, plain_tx_t.length)); //System.out.println(ComFn.bytesToHexString(cipher_tx_t, cipher_tx_t.length)); return cipher_tx_t; } //Ïò´®¿Ú·¢ËÍÐÅÏ¢·½·¨ public void sendMsg(byte[] byte_tx_buf) throws IOException { byte[] clr_buf = new byte[128]; while(inputStream.available() > 0) { inputStream.read(clr_buf); } outputStream.write(byte_tx_buf); if(++comm_tx_cnt > 32500) { comm_tx_cnt = 0; } } public void readMsg(ByteBuffer bbf_rx) throws IOException, InterruptedException { bbf_rx.clear(); int time_out = 0; byte[] rx_buf_t = new byte[280]; while(true) { if(inputStream.available() > 0) { time_out = 0; int rx_cnt_t = inputStream.read(rx_buf_t); if((bbf_rx.position()+rx_cnt_t) < (bbf_rx.capacity()-1)) { bbf_rx.put(rx_buf_t, 0, rx_cnt_t); } else { break; } } else { Thread.sleep(5); time_out++; if(0 == bbf_rx.position()) { if(time_out > 200) { break; } } else { if(time_out > 20) { break; } } } } bbf_rx.flip(); } public void CloseCommPort() { CommThreadRunning = false; } public void setCommCmd(int cmd, ByteBuffer data_buf) { dt_cmd = cmd; dt_datatofbs9100 = data_buf; } public void setCommCmd_DFU(boolean dfu_en, String dfu_file, JTextField show_area) { dt_dfu_en = dfu_en; dt_dfuFileName = dfu_file; dt_show_msg = show_area; } public void setCommCmdAck(int ack_t) { dt_cmd_ack = ack_t; dt_cmd_ack_time = new Date(); String wav_f = "6133.wav"; if(ack_t%2 == 0) { wav_f = "4577.wav"; } if(ack_t > 0) { new PlaySound(wav_f); } } public void sendFBS9100Data(int cmd, ByteBuffer bbf_tx) throws IOException { ByteBuffer bf_t = FBS9100_ComBuf.makeFbs9100CommBuf(255, cmd, bbf_tx); byte[] plain_tx_t = new byte[bf_t.limit()]; bf_t.get(plain_tx_t); //byte[] bt_t = FBS9100_ComBuf.makeFbs9100CommBuf(21, 0x15, ByteBuffer.allocate(0)).array(); byte[] cipher_tx_t = new byte[bf_t.limit()]; my_aes.ecb_encrypt(plain_tx_t, cipher_tx_t, plain_tx_t.length); //System.out.println(ComFn.bytesToHexString(plain_tx_t, plain_tx_t.length)); outputStream.write(cipher_tx_t); if(++comm_tx_cnt > 32500) { comm_tx_cnt = 0; } } public void run() { System.out.println("Thread start"); while(true == CommThreadRunning) { //System.out.println(dt_dfu_en); try { if(false == dt_dfu_en) { sendMsg(makeCommTxData()); readMsg(CommRxBuffer); byte[] cipher_buf = new byte[CommRxBuffer.limit()]; byte[] plain_buf = new byte[CommRxBuffer.limit()]; CommRxBuffer.get(cipher_buf); System.out.println(ComFn.bytesToHexString(cipher_buf,cipher_buf.length)); System.out.println(ComFn.bytesToHexString(plain_buf,plain_buf.length)); my_aes.ecb_decrypt(cipher_buf, plain_buf, cipher_buf.length); //System.out.println(ComFn.bytesToHexString(cipher_buf, cipher_buf.length)); //System.out.println(ComFn.bytesToHexString(plain_buf, plain_buf.length)); getDataFromCommBuf(plain_buf); Thread.sleep(500); } else { //--------------------------- BOOTLOADER_CMD_WRITE-----------------------------// String dfu_text_inf = "FBS9100S DFU Start."; dt_show_msg.setText(dfu_text_inf); boolean prog_ok = false; FileInputStream fis = null; try { File f = new File(dt_dfuFileName); long file_len = f.length(); byte[] buf_to_flash = new byte[FBS9100_DFU.DFU_BUF_LEN]; Thread.sleep(100); fis = new FileInputStream(f); int dfu_datablock_num = 1; int percent = 0; while(true) { //====================================// if((false == dt_dfu_en) || (false == CommThreadRunning)) { dfu_text_inf = "DFU Manual Stop . . ."; dt_show_msg.setText(dfu_text_inf); break; } //====================================// for(int n=0; n 0) { Thread.sleep(1); for(int cnt_t=0; cnt_t<3; cnt_t++) { sendFBS9100Data(FBS9100_ComBase.CMD_FBS9100_WriteDFU, m_FBS9100_DFU.getWriteByteBuffer(dfu_datablock_num, buf_to_flash, data_len_towrite)); readMsg(FBS9100RxBuffer); byte[] cipher_buf = new byte[FBS9100RxBuffer.limit()]; byte[] plain_buf = new byte[FBS9100RxBuffer.limit()]; FBS9100RxBuffer.get(cipher_buf); my_aes.ecb_decrypt(cipher_buf, plain_buf, cipher_buf.length); System.out.println(ComFn.bytesToHexString(plain_buf, plain_buf.length)); FBS9100RxBuffer.position(0); FBS9100RxBuffer.put(plain_buf); FBS9100RxBuffer.flip(); if(true == m_FBS9100_DFU.checkDfuWriteAckBuf(FBS9100RxBuffer)) { if(m_FBS9100_DFU.DataBlockIndex == dfu_datablock_num) { prog_ok = true; break; } } else { prog_ok = false; Thread.sleep(500); } } if(false == prog_ok) { dfu_text_inf = "DFU Write Error!"; dt_show_msg.setText(dfu_text_inf); break; } else { dfu_datablock_num += 1; } int tran_len_t = dfu_datablock_num*FBS9100_DFU.DFU_BUF_LEN; if(percent < (tran_len_t*100)/file_len) { percent = (int) ((tran_len_t*100)/file_len); if(percent > 100) { percent = 100; } dt_show_msg.setText(String.format("DFU Write: %d%% Done.\n", percent)); } } else { dfu_text_inf = "DFU Write: 100% Done!\n"; dt_show_msg.setText(dfu_text_inf); System.out.println(dfu_text_inf); break; } } } catch (IOException | InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } finally { try { fis.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } //*********************************************************************************// //*********************************************************************************// //*********************************************************************************// //*********************************************************************************// if((true == prog_ok) && (true == dt_dfu_en) && (true == CommThreadRunning)) { //*********************************************************************************// boolean check_ok = false; FileInputStream fis_ck = null; try { File f_ck = new File(dt_dfuFileName); long file_len_ck = f_ck.length(); byte[] buf_check = new byte[FBS9100_DFU.DFU_BUF_LEN]; Thread.sleep(100); fis_ck = new FileInputStream(f_ck); int check_datablock_num = 1; int percent = 0; while(true) { //====================================// if((false == dt_dfu_en) || (false == CommThreadRunning)) { dfu_text_inf = "DFU Check Manual Stop . . ."; dt_show_msg.setText(dfu_text_inf); break; } //====================================// for(int n=0; n 0) { Thread.sleep(1); for(int cnt_t=0; cnt_t<3; cnt_t++) { sendFBS9100Data(FBS9100_ComBase.CMD_FBS9100_ReadDFU, m_FBS9100_DFU.getReadByteBuffer(check_datablock_num, len_buf_check)); readMsg(FBS9100RxBuffer); byte[] cipher_buf = new byte[FBS9100RxBuffer.limit()]; byte[] plain_buf = new byte[FBS9100RxBuffer.limit()]; FBS9100RxBuffer.get(cipher_buf); my_aes.ecb_decrypt(cipher_buf, plain_buf, cipher_buf.length); FBS9100RxBuffer.position(0); FBS9100RxBuffer.put(plain_buf); FBS9100RxBuffer.flip(); if(true == m_FBS9100_DFU.checkDfuReadAckBuf(FBS9100RxBuffer)) { if(m_FBS9100_DFU.DataBlockIndex == check_datablock_num) { byte[] s_buf = new byte[len_buf_check]; FBS9100RxBuffer.get(s_buf); check_ok = true; for(int cn=0; cn 100) { percent = 100; } dt_show_msg.setText(String.format("DFU File Check: %d%% Done.\n", percent)); } } else { dfu_text_inf = "DFU File Check: 100% Done!\n"; dt_show_msg.setText(dfu_text_inf); break; } } } catch (IOException | InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } finally { try { fis_ck.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } //*********************************************************************************// } //*********************************************************************************// //*********************************************************************************// //---------------------------------------------------------------------------------// dt_dfu_en = false; //---------------------------------------------------------------------------------// //*********************************************************************************// //*********************************************************************************// } } catch (InterruptedException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); CloseCommPort(); JOptionPane.showMessageDialog(null, "FBS9100 ÉÏλ»ú´®¿ÚÒì³£: " + e.getMessage()); } } /******************************************/ serialPort.close(); /******************************************/ System.out.println("ZDHJ CommPort is quit!"); } /*********************************************************************************************/ /*********************************************************************************************/ /*********************************************************************************************/ /*********************************************************************************************/ public String getDataFromCommBuf(final byte[] bytes) { ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.order(ByteOrder.LITTLE_ENDIAN); bf.put(bytes); bf.flip(); String msg = ""; if(true == m_FBS_Cmd.putByteBuffer(bf)) { System.out.println(m_FBS_Cmd.CMD); //------------------- ¶ÁÈ¡FBS9100µçѹµçÁ÷Êý¾Ý -------------------- if(FBS9100_ComBase.CMD_GetVIData == m_FBS_Cmd.CMD) { if(true == m_FBS_VCData.m_SysState.putByteBuffer(bf)) { if(true == m_FBS_VCData.putByteBuffer(bf)) { System.out.println("»ñÈ¡µçѹµçÁ÷Êý¾Ý"); if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } } } } //------------------- ¶ÁÈ¡FBS9100ÄÚ×è²âÊÔ״̬ ----------------------- if(FBS9100_ComBase.CMD_GetResTestState == m_FBS_Cmd.CMD) { if(true == m_ResTestState.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get ResTest State from FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100ÈÝÁ¿²âÊÔ״̬ ----------------------- if(FBS9100_ComBase.CMD_GetDischargeState == m_FBS_Cmd.CMD) { if(true == m_CapTestState.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get CapTest State from FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100³äµç²âÊÔ״̬ ----------------------- if(FBS9100_ComBase.CMD_GetChargeState == m_FBS_Cmd.CMD) { if(true == m_ChrTestState.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get ChrTest State from FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100µç³Ø²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_GetBattParam == m_FBS_Cmd.CMD) { if(true == m_FBS_BattParam.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get battparam from FBS9100 OK!!!"; } } //------------------- ÉèÖÃFBS9100µç³Ø²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_SetBattParam == m_FBS_Cmd.CMD) { if(true == m_FBS_BattParam.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Set battparam to FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100ϵͳ²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_GetSYSSetParam == m_FBS_Cmd.CMD) { if(true == m_FBS_SystemParam.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get sysparam from FBS9100 OK!!!"; } } //------------------- ÉèÖÃFBS9100ϵͳ²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_SetSYSSetParam == m_FBS_Cmd.CMD) { if(true == m_FBS_SystemParam.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Set sysparam to FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100·Åµç²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_GetDischargeParm == m_FBS_Cmd.CMD) { if(true == m_FBS_DiscParamFromDev.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get DischargeParm from FBS9100 OK!!!"; } } //------------------- ÉèÖÃFBS9100·Åµç²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_SetDischargeParm == m_FBS_Cmd.CMD) { if(true == m_FBS_DiscParam.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Set DischargeParam to FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100³äµç²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_GetChargeParm == m_FBS_Cmd.CMD) { if(true == m_FBS_ChargeParam.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get ChargeParam from FBS9100 OK!!!"; } } //------------------- ÉèÖÃFBS9100³äµç²ÎÊý ------------------------- else if(FBS9100_ComBase.CMD_SetChargeParm == m_FBS_Cmd.CMD) { if(true == m_FBS_ChargeParam.putByteBuffer(bf)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Set ChargeParam to FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100ÈÝÁ¿ÄÚ×è²âÊÔÊý¾Ý ------------------ else if((FBS9100_ComBase.CMD_GetMonomerRES == m_FBS_Cmd.CMD) ||(FBS9100_ComBase.CMD_GetMonomerTMP == m_FBS_Cmd.CMD) /*||(FBS_ComBase.CMD_GetMonomerCAP == m_FBS_Cmd.CMD) ||(FBS_ComBase.CMD_GetMonomerChargeCAP == m_FBS_Cmd.CMD)*/) { if(true == m_FBS_ResCapData.putByteBuffer(bf, m_FBS_Cmd.CMD)) { if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get MonomerCAP or MonomerRES from FBS9100 OK!!!"; } } //------------------- ¶ÁÈ¡FBS9100ÈÎÎñÁбí ------------------------- else if(FBS9100_ComBase.CMD_GetDeviceTaskInf == m_FBS_Cmd.CMD) { //m_TaskList.position(0); m_TaskList = (bf); if(++comm_rx_cnt > 32500) { comm_rx_cnt = 0; } msg = "Get CMD_GetDeviceTaskInf From FBS9100 OK!!!"; //System.out.println(ComFn.getString(m_TaskList)); } } System.out.println("msg"+msg+"================"+m_FBS_Cmd.CMD); return msg; } /*********************************************************************************************/ }