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

相关推荐
*才华有限公司*22 分钟前
安卓前后端连接教程
android
氦客1 小时前
Android Compose中的附带效应
android·compose·effect·jetpack·composable·附带效应·side effect
雨白1 小时前
Kotlin 协程的灵魂:结构化并发详解
android·kotlin
我命由我123451 小时前
Android 开发问题:getLeft、getRight、getTop、getBottom 方法返回的值都为 0
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
Modu_MrLiu1 小时前
Android实战进阶 - 用户闲置超时自动退出登录功能详解
android·超时保护·实战进阶·长时间未操作超时保护·闲置超时
Jeled2 小时前
Android 网络层最佳实践:Retrofit + OkHttp 封装与实战
android·okhttp·kotlin·android studio·retrofit
信田君95272 小时前
瑞莎星瑞(Radxa Orion O6) 基于 Android OS 使用 NPU的图片模糊查找APP 开发
android·人工智能·深度学习·神经网络
tangweiguo030519872 小时前
Kotlin 实现 Android 网络状态检测工具类
android·网络·kotlin
nvvas3 小时前
Android Studio JAVA开发按钮跳转功能
android·java·android studio
怪兽20144 小时前
Android多进程通信机制
android·面试