android通过红外发送数据给红外设备

最近在做有智能表具通讯的时候,想通过手机的红外向表具发送指令,但找了网上的说明,对于android红外的通讯示例非常少,大多数是讲的遥控器的通讯,去国外网站上扒了一下,还真有这方面内容,大致的通讯过程,后面有时间再分析,需要根据具体的波特率进行调整,我们的设备是2400 停止位1 偶校验,如果是无校验或者奇校验,代码需要调整。

java 复制代码
package com.example.ifrareddemo;

import android.util.Log;

import java.io.Console;
import java.util.ArrayList;
import java.util.List;

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

    private static final float CARRIER_FREQUENCY = 38400f; // The IR carrier frequency in hertz.
    private final float BAUD_RATE = 2400f;
    private final float MICROSEC_PER_SEC = 1000000f;
    private final int START_BIT = 0;
    private final int STOP_BIT = 1;
    private final int[] pattern; // The toggle pattern in microseconds to transmit.
    private int[] oldApiPattern; // The toggle pattern in pulses to transmit.
    private final String hexCode; // The MwM hex code

    /**
     * Creates an MahouCode with the given MwM hex code.
     *
     * @param code the hex code.
     */
    public MahouCode(String code) {
        List<Integer> hexList = parseByteValues(code);

        hexCode = codeListToString(hexList);

        List<Integer> patternList;
        patternList = generatePattern(hexCode, true);
        pattern = convertIntegers(patternList);
    }

    /**
     * Converts a list of integers to a hex string.
     */
    private static String codeListToString(List<Integer> hexList) {
        StringBuilder sb = new StringBuilder();
        for (int item : hexList) {
            sb.append(String.format("%02X", item));
            sb.append(' ');
        }

        return sb.toString().trim();
    }

    /**
     * Parses the byte values from the hex code string and returns it as a list of integers.
     *
     * @param hexCode The hex code string. Spaces are ignored.
     * @return List of values of each hex byte.
     */
    private static List<Integer> parseByteValues(String hexCode) {
        List<Integer> result = new ArrayList<>();
        String codeString = hexCode.replace(" ", "").trim();
        int size = codeString.length();

        if (size % 2 == 0) {
            for (String s : getParts(codeString, 2)) {
                result.add(Integer.parseInt(s, 16));
            }
        }

        return result;
    }

    /**
     * Split a string into parts by partition size.
     *
     * @param string        String to be partitioned
     * @param partitionSize length of parts
     * @return list of parts
     */
    private static List<String> getParts(String string, int partitionSize) {
        List<String> parts = new ArrayList<>();
        int len = string.length();
        for (int i = 0; i < len; i += partitionSize) {
            parts.add(string.substring(i, Math.min(len, i + partitionSize)));
        }
        return parts;
    }

    /**
     * Automatically convert the given code to a 9x code. Do not include CRC.
     *
     * @param code9x string without the starting 9X and ending CRC.
     * @return the full code with the starting 9X and ending CRC.
     */
    public static String parse9x(String code9x) {
        List<Integer> integers = parseByteValues(code9x);
        integers.add(0, 0x90 - 1 + integers.size());
        integers.add(calcCrc(integers));

        return codeListToString(integers);
    }

    /**
     * Calculates the CRC for the given list of integers.
     *
     * @param data The list of integers that represents the hex code
     * @return The calculated CRC value.
     */
    private static int calcCrc(List<Integer> data) {
        int crc = 0;

        for (int i = 0; i < data.size(); i++) {
            crc = CRC_TABLE[crc ^ data.get(i)];
        }

        return crc;
    }

    /**
     * Gets the carrier frequency.
     *
     * @return the carrier frequency.
     */
    public static int getCarrierFrequency() {
        return (int) CARRIER_FREQUENCY;
    }

    /**
     * Gets the hex code.
     *
     * @return the hex code.
     */
    public String getCode() {
        return hexCode;
    }

    /**
     * Gets the toggle pattern.
     *
     * @return the toggle pattern.
     */
    public int[] getPattern() {
        return pattern;
    }

    /**
     * Gets the old API toggle pattern.
     *
     * @return the old API toggle pattern.
     */
    public int[] getOldApiPattern() {
        if (oldApiPattern == null) {
            oldApiPattern = convertIntegers(generatePattern(hexCode, false));
        }

        return oldApiPattern;
    }

    /**
     * Convert list of integers to primitive array.
     *
     * @param integers list of integers.
     * @return array of int.
     */
    private int[] convertIntegers(List<Integer> integers) {
        int[] ret = new int[integers.size()];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = integers.get(i);
        }
        return ret;
    }

    /**
     * Generates the toggle pattern in terms of microseconds if isNew is true; otherwise, in
     * terms of pulse.
     *
     * @param code  the hex code string.
     * @param isNew the flag to indicate if generating for Android 4.4.3 or newer.
     * @return the toggle pattern in terms based on isNew.
     */
    private List<Integer> generatePattern(String code, boolean isNew) {
        // If API is new (>= 4.4.3), calculate microseconds per bit, else calculate pulse per bit.
        float multiplier = (isNew) ? (MICROSEC_PER_SEC / BAUD_RATE) : (CARRIER_FREQUENCY / BAUD_RATE);

        List<Integer> patternList = new ArrayList<>();
        List<Integer> buffer = parseByteValues(code);

        buffer = toTogglePattern(buffer);


        for (int num = 0; num < buffer.size(); num++) {
            patternList.add(Math.round(buffer.get(num) * multiplier));
        }


        return patternList;
    }

    /**
     * Transforms the list of code values to toggle pattern.
     *
     * @param codeValues the list of integer values of the hex codes.
     * @return the alternating toggle pattern in terms of bits.
     */
    private List<Integer> toTogglePattern(List<Integer> codeValues) {
        StringBuilder myStr = new StringBuilder();

        for (int value : codeValues) {
            // Convert byte value to binary
            StringBuilder binaryString = new StringBuilder(String.format("%8s", Integer.toString(value, 2)).replace(' ', '0'));

            myStr.append(START_BIT)             //起始位
                    .append(binaryString.reverse()) // Reverse to send least significant bit first
                    .append(GetCheck(binaryString))  //偶校验 
                    .append(STOP_BIT);               //停止位
        }

        String fullString = myStr.toString();

        Log.d("IR",fullString);

        List<Integer> togglePattern = new ArrayList<>();

        // Count the occurrence of the same consecutive bits and add them to the pattern list
        char c = fullString.charAt(0);
        int count = 1;

        for (int i = 1; i < fullString.length(); i++) {
            if (c == fullString.charAt(i)) {
                count++;
            } else {
                togglePattern.add(count);
                c = fullString.charAt(i);
                count = 1;
            }
        }

        togglePattern.add(count);

        return togglePattern;
    }

    public String GetCheck(StringBuilder sb)
    {
        String str=sb.toString();
        return str.replace("0","").length()%2==0?"0":"1";
    }
}

上面的是帮助类,调用也比较简单

java 复制代码
public ConsumerIrManager mCIR;

    public TextView txtResult;

    public Button btnSend;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        txtResult=findViewById(R.id.txtResult);

        btnSend=findViewById(R.id.btnSend);


        mCIR = (ConsumerIrManager) getSystemService(Context.CONSUMER_IR_SERVICE);/* 获取系统的红外遥控服务 */
        if (!mCIR.hasIrEmitter()) {     /* 检查是否有红外发射器 */

            txtResult.setText("不支持红外");
        } else {
            /* Find IR!! */
            txtResult.setText("支持红外");
        }

        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String str="FEFEFEFEFEFE680000AAAAAAAAAAAAAA01C111F01000D294EDD417EE63EB3AC786BEA46C7CCBF716";

                MahouCode mahouCode=new MahouCode(str);

                mCIR.transmit(38400,mahouCode.getPattern());

            }
        });

        handPermission();
    }

    public void handPermission() {
        // 定位权限组
        String[] mPermissionGroup = new String[]{
                Manifest.permission.TRANSMIT_IR};

        // 过滤已持有的权限
        List<String> mRequestList = new ArrayList<>();
        for (String permission : mPermissionGroup) {
            if ((ContextCompat.checkSelfPermission(this, permission)
                    != PackageManager.PERMISSION_GRANTED)) {
                mRequestList.add(permission);
            }
        }

        // 申请未持有的权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !mRequestList.isEmpty()) {
            ActivityCompat.requestPermissions(this, mRequestList.toArray(
                    new String[mRequestList.size()]), 100);
        }
    }

帮助类git地址:https://github.com/daveenguyen/MahouCode/blob/master/src/main/java/com/daveenguyen/mahoucode/MahouCode.java

相关推荐
Dingdangr3 小时前
Android中的Intent的作用
android
技术无疆3 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
GEEKVIP3 小时前
Android 恢复挑战和解决方案:如何从 Android 设备恢复删除的文件
android·笔记·安全·macos·智能手机·电脑·笔记本电脑
Jouzzy10 小时前
【Android安全】Ubuntu 16.04安装GDB和GEF
android·ubuntu·gdb
极客先躯11 小时前
java和kotlin 可以同时运行吗
android·java·开发语言·kotlin·同时运行
Good_tea_h13 小时前
Android中的单例模式
android·单例模式
计算机源码社18 小时前
分享一个基于微信小程序的居家养老服务小程序 养老服务预约安卓app uniapp(源码、调试、LW、开题、PPT)
android·微信小程序·uni-app·毕业设计项目·毕业设计源码·计算机课程设计·计算机毕业设计开题
丶白泽19 小时前
重修设计模式-结构型-门面模式
android
晨春计20 小时前
【git】
android·linux·git
标标大人21 小时前
c语言中的局部跳转以及全局跳转
android·c语言·开发语言