//
//  DKCmdTool.m
//  DKWF_Example
//
//  Created by nana on 2020/7/3.
//  Copyright © 2020 304635659@qq.com. All rights reserved.
//

#import "DKCmdTool.h"

@implementation DKCmdTool



NSData *dataWithCmd(JFDeviceSendCommand command) {
    NSMutableData *rdata = [[NSMutableData alloc] init];
    /// header1 和 header2 没有合在一起, 懒得交换
    int header1 = 0x55;
    int header2 = 0xaa;
    int dataLen = 0x00; //带计算
    int device1 = 0x00;
    int device2 = 0x1D;
    int commtype = 0x31;
    int cmdStatus = 0x02;
    NSData *data = [NSData data]; ///

    switch (command) {
        case JFDeviceSendCommandLightsRG:
        {
            dataLen = 0x06;
            commtype = 0x31;
            NSInteger x = 0x0006;
            data = [NSData dataWithBytes:&x length:2];
            break;
        }
        case JFDeviceSendCommandLightsJXPZ:
        {
            dataLen = 0x06;
            commtype = 0x31;
            NSInteger x = 0x0106;
           data = [NSData dataWithBytes:&x length:2];
            break;
        }
        case JFDeviceSendCommandLightsPHPZ:
        {
            dataLen = 0x06;
            commtype = 0x31;
            NSInteger x = 0x0206;
           data = [NSData dataWithBytes:&x length:2];
            break;
        }
        case JFDeviceSendCommandLightsUV:
        {
            dataLen = 0x06;
            commtype = 0x31;
            NSInteger x = 0x0306;
           data = [NSData dataWithBytes:&x length:2];
            break;
        }
        case JFDeviceSendCommandLightsOFF:
        {
            dataLen = 0x06;
            commtype = 0x31;
            NSInteger x = 0x0406;
           data = [NSData dataWithBytes:&x length:2];
            break;
        }
        case JFDeviceSendCommandLightsCurrent:
        {
            dataLen = 0x05;
            commtype = 0x33;
            NSInteger x = 0x05;
           data = [NSData dataWithBytes:&x length:1];
            break;
        }
        case JFDeviceSendCommandBatteryLevel:
        {
            dataLen = 0x05;
            commtype = 0x33;
            NSInteger x = 0x04;
           data = [NSData dataWithBytes:&x length:1];
            break;
        }
        case JFDeviceSendCommandFirmwareVersion:
         {
            dataLen = 0x05;
            commtype = 0x33;
            NSInteger x = 0x18;
            data = [NSData dataWithBytes:&x length:1];
             break;
         }
        case JFDeviceRecvCommandCheckWaterOil:
        {
            dataLen = 0x05;
            commtype = 0x33;
            NSInteger x = 0x03;
           data = [NSData dataWithBytes:&x length:1];
            break;
        }
        case JFDeviceRecvCommandHaveWaterOil:
        {
            dataLen = 0x05;
            commtype = 0x33;
            NSInteger x = 0x09;
           data = [NSData dataWithBytes:&x length:1];
            break;
        }
        case JFDeviceRecvCommandXiaoYanWaterOil:
        {
            dataLen = 0x05;
            commtype = 0x33;
            NSInteger x = 0x0A;
           data = [NSData dataWithBytes:&x length:1];
            break;
        }
        case JFDeviceRecvCommandXiaoYanHeightWaterOil:
        {
            dataLen = 0x05;
            commtype = 0x33;
            NSInteger x = 0x0B;
           data = [NSData dataWithBytes:&x length:1];
            break;
        }
        default:
            break;
    }
    
    [rdata appendBytes:&header1 length:1];
    [rdata appendBytes:&header2 length:1];
    [rdata appendBytes:&dataLen length:1];
    [rdata appendBytes:&device1 length:1];
    [rdata appendBytes:&device2 length:1];
    [rdata appendBytes:&commtype length:1];
    [rdata appendBytes:&cmdStatus length:1];
    [rdata appendData:data];
    int CRC16check = _OSSwapInt16(CRC_16_Check([rdata subdataWithRange:NSMakeRange(2, rdata.length-2)]));
    [rdata appendBytes:&CRC16check length:2];
    
    return rdata;
}


bool cmdWithData(NSData *inData,int *outValue, JFDeviceSendCommand *cmd){
    if (inData.length< 10) {
        return false;
    }

    int header1 = 0x55;
    int header2 = 0xaa;
    int dataLen = 0x00; //带计算
    int device1 = 0x00;
    int device2 = 0x1D;
    int commtype = 0x31;
    int cmdStatus = 0x02;
    
    [inData getBytes:&header1 range:NSMakeRange(0, 1)];
    [inData getBytes:&header2 range:NSMakeRange(1, 1)];
    [inData getBytes:&dataLen range:NSMakeRange(2, 1)];
    [inData getBytes:&device1 range:NSMakeRange(3, 1)];
    [inData getBytes:&device2 range:NSMakeRange(4, 1)];
    [inData getBytes:&commtype range:NSMakeRange(5, 1)];
    [inData getBytes:&cmdStatus range:NSMakeRange(6, 1)];
    
    NSInteger x = 0;
    if (commtype == 0x33 &&
        cmdStatus == 0x01) {
        [inData getBytes:&x range:NSMakeRange(7, 1)];
        [inData getBytes:outValue range:NSMakeRange(8, 1)];
    }
    if (commtype == 0x31) {
        [inData getBytes:&x range:NSMakeRange(7, inData.length-7-2)];
    }

    
    switch (x) {
        case 0x0006 :
        {
           *cmd = JFDeviceSendCommandLightsRG;
            break;
        }
        case 0x0106 :
        {
            *cmd = JFDeviceSendCommandLightsJXPZ;
            break;
        }
        case 0x0206 :
        {
            *cmd = JFDeviceSendCommandLightsPHPZ ;
            break;
        }
        case 0x0306 :
        {
            *cmd = JFDeviceSendCommandLightsUV;
            break;
        }
        case 0x0406 :
        {
            *cmd = JFDeviceSendCommandLightsOFF;
            break;
        }
        case 0x05 :
        {
            *cmd = JFDeviceSendCommandLightsCurrent;
            break;
        }
        case  0x04:
        {
            *cmd = JFDeviceSendCommandBatteryLevel;
            break;
        }
        case 0x18 :
         {
            *cmd = JFDeviceSendCommandFirmwareVersion;
             break;
         }
        case  0x07:
        {
            *cmd = JFDeviceRecvCommandPhotograph;
            break;
        }
        case  0x03:
        {
            *cmd = JFDeviceRecvCommandCheckWaterOil;
            break;
        }
        case  0x09:
        {
            *cmd = JFDeviceRecvCommandHaveWaterOil;
            break;
        }
        case  0x0A:
        {
            *cmd = JFDeviceRecvCommandXiaoYanWaterOil;
            break;
        }
        case  0x0B:
        {
            *cmd = JFDeviceRecvCommandXiaoYanHeightWaterOil;
            break;
        }
        default:
            break;
    }
    
    return true;
}

/*************************************************************************** CRC 校验步骤:
 1、 设置 CRC 寄存器， 并给其赋值 FFFF(hex)
 2、 将数据的第一个 8-bit 字符与 16 位 CRC 寄存器的低 8 位进行异或， 并把结果
 存器
 3、 CRC 寄存器向右移一位， MSB 补零， 移出并检查 LSB
 4、 如果 LSB 为 0， 重复第三步; 若 LSB 为 1， CRC 寄存器与多项式码相异或
 5、 重复第 3 与第 4 步直到 8 次移位全部完成。 此时一个 8-bit 数据处理完毕
 6、 重复第 2 至第 5 步直到所有数据全部处理完成
 7、 最终 CRC 寄存器的内容即为 CRC 值
 8、 CRC(16 位)多项式为 X16+X15+X2+1，其对应校验二进制位列为 1 1000 0000 0000 0101 //函数名称: unsigned int CRC_16_Check(void)
 //函数功能: CRC16 校验 ****************************************************************************/
unsigned int CRC_16_Check(NSData *databuf) //0x55 0xAA 0x06 0x00 0x1D 0x31 0x02 0x06 0x00
{
    int len = (int)databuf.length; //字节长度
    unsigned int CRC_index = 0xffff;
    for(int i = 0; i < len; i++)
    {
        unsigned int buffer = 0; // i= 0 :0x55, i = 1 :0xaa
        [databuf getBytes:&buffer range:NSMakeRange(i, 1)]; //取数据 存入 buffer 中
        CRC_index ^= buffer; for(int j = 0; j < 8; j++) {
            if(CRC_index & 0x0001)
            {
                CRC_index >>= 1;
                CRC_index ^= 0xa001;
            }
            else {
                CRC_index >>= 1;
            }
        }
        
    }
    return CRC_index; // 0x9E 0X3D
}



NSData *sendScanWIFI() {
    return [@"<?xml version=\"1.0\" encoding=\"utf-8\"?><CMD_REQ code=1 index=1/>" dataUsingEncoding:NSUTF8StringEncoding];
}

NSData *sendSetWIFI(NSString *wifiName ,NSString *WifiPwd ) {
    NSString *cmdString = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?><CMD_REQ code=2 index=2><SSID>%@</SSID><PASSWORD>%@</PASSWORD></CMD_REQ>",wifiName,WifiPwd];
    return [cmdString dataUsingEncoding:NSUTF8StringEncoding];
}

NSData *sendGetWIFIInfo() {
    return [@"<?xml version=\"1.0\" encoding=\"utf-8\"?><CMD_REQ code=3 index=3/>" dataUsingEncoding:NSUTF8StringEncoding];
}

NSData *sendSetCameraFPS(int FPS) {
    if (FPS < 10 || FPS > 25) {
        FPS = 10;
    }
    NSString *cmdString = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?><CMD_REQ code=4 index=4><FPS>%d</FPS></CMD_REQ>",FPS];
    return [cmdString dataUsingEncoding:NSUTF8StringEncoding];
}

NSData *sendSetCameraResolutionRatio(NSString *rr) {
    if (![@"640x480800x6001280x7201920x1080" containsString:rr]) {
        rr = @"1280x720";
    }
        NSString *cmdString = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?><CMD_REQ code=5 index=5><VGA>%@</VGA></CMD_REQ>",rr];
    return [cmdString dataUsingEncoding:NSUTF8StringEncoding];
}

NSData *sendGetCameraInfo() {
    return [@"<?xml version=\"1.0\" encoding=\"utf-8\"?><CMD_REQ code=6 index=6/>" dataUsingEncoding:NSUTF8StringEncoding];
}

@end
