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

相关推荐
张拭心4 分钟前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
张拭心14 分钟前
Android 17 来了!新特性介绍与适配建议
android·前端
Kapaseker2 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴3 小时前
Android17 为什么重写 MessageQueue
android
阿巴斯甜1 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android