PHP:CRC16数据校验算法


需求

在公司写个智能洗车的东西,大概流程就是车通过扫描进入车库,洗完车在扫描一次出车库。但是写代码的时候发现显示屏通讯协议中的数据需要crc16校验,那就得单独写,php有自带的crc32,就是没有16。

实现代码

function crc16($string, $length = 0) {

    $auchCRCHi = array(0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
        0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
        0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
        0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
        0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
        0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
        0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
        0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
        0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
        0x40
    );
    $auchCRCLo = array(0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
        0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
        0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
        0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
        0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
        0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
        0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
        0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
        0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
        0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
        0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
        0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
        0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
        0x40
    );
    $length = ($length <= 0 ? strlen($string) : $length);
    $uchCRCHi = 0xFF;
    $uchCRCLo = 0xFF;
    $uIndex = 0;
    for ($i = 0; $i < $length; $i++) {
        $uIndex = $uchCRCLo ^ ord(substr($string, $i, 1));
        $uchCRCLo = $uchCRCHi ^ $auchCRCHi[$uIndex];
        $uchCRCHi = $auchCRCLo[$uIndex];
    }
    return(chr($uchCRCLo) . chr($uchCRCHi));
}

具体使用

$str = "0064FFFFE30901000005000A000000" //15位代加密数据
$s = pack('H*',$str);  //数据处理16进制字符串
$t = $this->crc16($s);  //校验数据结果位A045
$res = unpack("H*", $s.$t);  //由16进制转成字符串
echo $res;  //最终结果0064FFFFE30901000005000A000000A045

Nodejs:创建个express项目,实现上传微信小程序


前言

自己有个利用miniprogram-ci上传微信小程序的想法,这里设计到了nodejs npm的知识,先从一个hello world Web项目开始,再慢慢编写相关接口。

涉及

  • nodejs
  • npm
  • 多进程
  • express
  • miniprogram-ci

实现过程

一、创建node项目

新建个项目文件夹node_wxapp 然后创建项目配置文件

cd 项目文件
mpn init

进入到项目所在的目录之后我们就可以直接执行npm init,执行了npm init之后,会让我们填写一些配置信息,如果还不知道怎么填写的话可以一路回车,因为我已经配置过了,所以这里就直接贴图:

  • package name:你的项目名字叫啥
  • version:版本号
  • description:对项目的描述
  • entry point:项目的入口文件(一般你要用那个js文件作为node服务,就填写那个文件)
  • test command:项目启动的时候要用什么命令来执行脚本文件(默认为node app.js)
  • git repository:如果你要将项目上传到git中的话,那么就需要填写git的仓库地址(这里就不写地址了)
  • keywirds:项目关键字(我也不知道有啥用,所以我就不写了)
  • author:作者的名字(也就是你叫啥名字)
  • license:发行项目需要的证书(这里也就自己玩玩,就不写了)

微信图片_20210521153312.png

最后文件中出现package.json文件其主要内容有:

{
  "name": "node_wxapp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js" // 后添加的,主要是为了npm start自动运行
  },
  "author": "",
  "license": "ISC"
}

二、安装依赖

这里用到了web项目,所以用express框架

npm install express --save
npm install miniprogram-ci --save

这里在项目目录中会生成node_module文件夹和package-lock.json文件

三、创建编辑项目主文件index.js

1.输出hello world

var express = require('express');
var app = express();
 
//  主页输出 "Hello World"
app.get('/', function (req, res) {
   console.log("主页 GET 请求");
   var data = {"code":0,"data":"123"};
   res.send("Hello world");
})
 
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

这里直接在项目文件npm start,可以看到命令行打印应用实例,访问地址为 http://:::8081.
打开浏览器输入http://127.0.0.1:8081即可看到页面的hello world

2.进程管理


Python: 扫面网段+ssh连接执行命令


前言

有个小想法需要去实现,具体是扫描一个网段,找到那个开着ssh端口的ip,然后用现有的密钥连接或者用密码本连接。

涉及到的知识点

  • paramiko
  • socket
  • IPy

代码片段解析

整体代码

#!/usr/bin/python
# -*- coding:utf-8 -*-
 
import paramiko
import socket
import time
import sys
import IPy

def sshexeccmd(ip,cmd):
    try:

        ssh = paramiko.SSHClient()
        #add to host_allow
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password='yourpassword')
        pkey = paramiko.RSAKey.from_private_key_file('c:/Users/QY/Desktop/id_rsa')

        ssh.connect(hostname=ip,
                    port=22,
                    username='root',
                    pkey=pkey)

        stdin, stdout, stderr = ssh.exec_command(cmd)

        print(stdout.read())
        print(stderr.read())

        ssh.close()
    except Exception as e:
        print(e)


def portScanner(ip,port):
    server = (ip,port)
    sockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sockfd.settimeout(0.1)
    ret = sockfd.connect_ex(server)  #返回0则成功
    if not ret:
        sockfd.close()
        print('%s:%s is opened...' % (ip,port))
        return True
    else:
        sockfd.close()
        return False
        pass

if __name__ =='__main__':
    if len(sys.argv) != 4:
        print('python pyfile ip/24 port cmd')
        sys.exit()
    print('-' * 100)
    print('HOST: %s' % sys.argv[1])
    print('PORT: %s' % sys.argv[2])
    print('CMD: %s' % sys.argv[3])
    ips = IPy.IP(sys.argv[1])
    print('将要扫面 %s 个IP' % len(ips))
    for ip in ips:
        print("/*****%s*****/" % ip.strNormal(0))
        if portScanner(ip.strNormal(0),int(sys.argv[2])):
            print("开始对其进行ssh处理")
            sshexeccmd(ip.strNormal(0),sys.argv[3])
        print("/***********************/")
    # sshexeccmd(sys.argv[1],sys.argv[2])
    print('-' * 100)

Jquery:属性选择器(同时匹配多个条件,与或非)


前言

在处理ESA中的table内js代码的时候出现了问题,主要是为了让同一个div下的不同选项来处理不同的操作,为了处理除了两项不符合条件外的选择,需要用到jquery选择器的多个条件匹配来处理,然后整理了一下相关的与或非的条件及其组合。

代码

// 内部操作监听
$(elem).on("click",".esa-table-body [esa-event][esa-event!='checkbox'][esa-event!='radio']",function(e){
                
})
// 头尾时间监听
$(elem).on("click",".esa-table-head [esa-event],.esa-table-foot [esa-event],.esa-table-body [esa-event='checkbox'],[esa-event='radio']",function(e){
                
})

示例

示例代码

<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
    <script src="https://blog.bug-maker.com/admin/js/jquery.js?v=17.10.30"></script>
    <script type="text/javascript">
 
    $().ready(function(){
         
        debugger;// open console and click F10
        //多条件选择
        $('#table1 #td1-1,#td1-2').css('color','red');
        //选择内容不是id=td1
        $('#table2 tbody td:not(#td2-1)').css('color','green');
        //选择条件1 attr1="a1" 和 条件2 attr2="a2"的元素
        $('#table3 [attr1="a1"][attr2="a2"]').css('color','blue');
        //选择条件1 attr1="a1" 或者 条件2 attr2="a2"的元素
        $('#table4 [attr1="a1"],#table4 [attr2="a2"]').css('color','yellow');
 
        //选择不满足 条件1 attr1="a1" 的元素
        $('#table5 tbody td[attr1!="a1"]').css('color','purple');
         
        //选择不满足 条件1 attr1="a1" 或 条件2 attr2="a2"的元素
        $('#table6 tbody td:not([attr1="a1"],[attr2="a2"])').css('color','red');
        $('#table6 tbody td[attr1!="a1"][attr2!="a2"]').css('color','red');
 
        //选择不满足 条件1 attr1="a1" 和 条件2 attr2="a2"的元素
        $('#table7 tbody td:not([attr1="a1"][attr2="a2"])').css('color','red');
        $('#table7 tbody td([attr1!="a1"],[attr2!="a2"])').css('color','red');
 
        //选择tboy中td标签attr1!="a1" 和 所有标签中attr2!="a2", 即除了<td id="td3" attr1="a1" attr2="a2">3</td>的其它所有标签元素
        $('#table8 tbody td([attr1!="a1"],[attr2!="a2"])').css('color','red');
    })
 
    </script>
</head>
<body>
    <p>第一个:多条件选择</p>
    <table border="1px" id="table1">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td1-1">1</td><td id="td1-2">2</td><td id="td1-3" attr1="a1" attr2="a2">3</td><td id="td1-4" attr1="a1">4</td><td id="td1-5">5</td></tr></tbody>
    </table>
    <p>第二个:选择内容不是id=td1</p>
    <table border="1px" id="table2">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td2-1">1</td><td id="td2-2">2</td><td id="td2-3" attr1="a1" attr2="a2">3</td><td id="td2-4" attr1="a1">4</td><td id="td2-5">5</td></tr></tbody>
    </table>
    <p>第三个:选择条件1 attr1="a1" 和 条件2 attr2="a2"的元素</p>
    <table border="1px" id="table3">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td3-1">1</td><td id="td3-2">2</td><td id="td3-3" attr1="a1" attr2="a2">3</td><td id="td3-4" attr1="a1">4</td><td id="td3-5">5</td></tr></tbody>
    </table>
    <p>第四个:选择条件1 attr1="a1" 或者 条件2 attr2="a2"的元素</p>
    <table border="1px" id="table4">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td4-1">1</td><td id="td4-2">2</td><td id="td4-3" attr1="a1" attr2="a2">3</td><td id="td4-4" attr1="a1">4</td><td id="td4-5">5</td></tr></tbody>
    </table>
    <p>第五个:选择不满足 条件1 attr1="a1" 的元素</p>
    <table border="1px" id="table5">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td5-1">1</td><td id="td5-2">2</td><td id="td5-3" attr1="a1" attr2="a2">3</td><td id="td5-4" attr1="a1">4</td><td id="td5-5">5</td></tr></tbody>
    </table>
    <p>第六个:选择不满足 条件1 attr1="a1" 或 条件2 attr2="a2"的元素</p>
    <table border="1px" id="table6">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td6-1">1</td><td id="td6-2">2</td><td id="td6-3" attr1="a1" attr2="a2">3</td><td id="td6-4" attr1="a1">4</td><td id="td6-5">5</td></tr></tbody>
    </table>
    <p>第二个:选择不满足 条件1 attr1="a1" 和 条件2 attr2="a2"的元素</p>
    <table border="1px" id="table7">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td7-1">1</td><td id="td7-2">2</td><td id="td7-3" attr1="a1" attr2="a2">3</td><td id="td7-4" attr1="a1">4</td><td id="td7-5">5</td></tr></tbody>
    </table>
    <p>第二个:选择tboy中td标签attr1!="a1" 和 所有标签中attr2!="a2", 即除了<td id="td3" attr1="a1" attr2="a2">3</td>的其它所有标签元素</p>
    <table border="1px" id="table7">
        <thead><tr><td>One</td><td>Two</td><td>Three</td><td>Four</td><td>Five</td></tr></thead>
        <tbody><tr><td id="td8-1">1</td><td id="td8-2">2</td><td id="td8-3" attr1="a1" attr2="a2">3</td><td id="td8-4" attr1="a1">4</td><td id="td8-5">5</td></tr></tbody>
    </table>
</body>
</html>  

Python:文件mht转成png或jpg等形式的图片


需求来源

今天三婶找我帮忙,说这个文件在网上找了好长时间都没有一个好用的转换工具或者网站。在chrome里浏览样式还有问题,图片也显示不出来,但是在ie里是没问题的。
本来想用selenium+chrome来截图出来处理,那就没办法了,决定放弃了,但是发现selenium里也有ie的工具,我靠,那不就解决问题了么,那直接上代码。

需要环境

  • python3
  • selenium
  • IEDriverServer

过程

第一步 安装selenium

pip install selenium

第二步 下载IE驱动

1.下载IEDriverServer 选择版本号,IEDriverServer的版本号和Selenium的版本号一定要一致,安装selenium时记录版本号即为了在此处对应。
2.解压缩得到IEDriverServer.exe,并将其添加到环境变量的目录下 ,即python.exe所在目录或者像我一样,撇到其他目录后期配置目录即可。(如:C:Python37)
3.针对windows vista和windows 7上的IE7或者更高的版本,必须在IE选项设置的安全页中,4个区域的启用保护模式的勾选都去掉(或都勾上),即保持四个区域的保护模式是一致的。

第三步 上代码

import os
from selenium import webdriver
from selenium.common.exceptions import WebDriverException

source_path = 'e:/Desktop/新建文件夹/mhts/'
target_path = 'e:/Desktop/新建文件夹/result/'
# options = webdriver.IeOptions()
# options.add_argument('--headless')
# options.add_argument('--disable-gpu')
# options.add_argument('--no-sandbox')
# options.add_argument('window-size=1920x1080')
 
 
# driver = webdriver.Ie(executable_path=r"E:\Program Files\IEDriverServer.exe")
# driver.maximize_window()
# driver.get("e:/Desktop/新建文件夹/白春秀9月居家.mht")
# driver.get_screenshot_as_file(u'e:/Desktop/新建文件夹/白春秀9月居家.png')
# driver.quit()

files = os.listdir(source_path)
for fi in files:
    print("%s" % fi)
    driver = webdriver.Ie(executable_path=r"E:\Program Files\IEDriverServer.exe")
    driver.maximize_window()
    driver.get(source_path + fi)
    driver.get_screenshot_as_file(target_path + fi + ".jpg")
    driver.quit()

最后上张图片结束

微信图片编辑_20210312221916.jpg