天天看點

Android序列槽程式設計--開關燈Demo(附源碼)

1、項目簡述

第二次玩硬體了,第一次是通過區域網路控制門的開關,這次是通過ZB(大概就是這麼叫,具體名字不清楚)控制燈的開關,感覺控制硬體也就是給硬體發個byte數組而已。

這裡有個架構usb-serial-for-android 可以直接使用,但是裡面并沒有教你怎麼寫資料,我還是一個一個類裡面找write相關方法,後來終于找到了是通過UsbSerialPort類下的write(final byte[] src, final int timeoutMillis)方法實作資料的發送的。

2、實作後的感想

這個demo感覺挺難測試的,而且一旦發現問題,很難找到問題所在。 

測試難在于,電腦上的模拟器是沒法測試的(反正我的模拟器是測試失敗的),因為模拟器通路不到電腦的USB接口,在手機上也是很難測試,因為手機是沒法給外部接口供電的,除非你有這樣一根帶供電功能的OTG線。 

是以我們測試對象就是一些安卓裝置,比如說Android電視之類的。

3、操作步驟

(1)當你在初始界面獲得到序列槽資訊時 

(2)點選一個序列槽,可以進入到另一個Activity裡去 

(3)在這裡你就可以通過UsbSerialPort的write進行寫資料了。 

說的是這麼簡單,但是實際上第一次接觸的猿友應該是會感到很迷茫的。

4、主要代碼

    public void writeData(String data) {

        if(mSerialPort == null) return;

        try {

            //這裡需要對資料做一次處理,可能是因為接收方(台燈)那邊需要對資料解析,不一定每個接收方都需要處理,PS:我在這裡就踩了個坑了

            byte[] bytes = StringToBytes.getFCSData(data.getBytes()); 

            int result = mSerialPort.write(bytes, 1000);

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

9

10

這個就是我寫資料時的代碼,通過UsbSerialPort進行寫資料,但是我寫之前,先對傳進來的字元串進行處理,不處理的話,發送到燈上的資料是沒有用的,發送成功了,燈也不會亮。在此,我可是踩到了個大坑的。

因為這個demo要內建到項目中去,是以我把代碼整理了一下,隻需要在初始化一下,然後調用WriteData方法,即可發送資料了(前提是你得通路到了序列槽),具體代碼如下:

public class DeviceManager {

    private static final int MESSAGE_REFRESH = 101;

    private static final long REFRESH_TIMEOUT_MILLIS = 5000;

    private List<UsbSerialPort> mPortList = new ArrayList<>();

    private UsbManager mUsbManager;

    private UsbSerialPort mSerialPort;

    private SerialInputOutputManager mSerialIoManager;

    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();

    public Context mContext;

    public DeviceManager(Context context) {

        mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

        mContext = context;

    }

    private final Handler mHandler = new Handler() {

        @Override

        public void handleMessage(Message msg) {

            switch (msg.what) {

                case MESSAGE_REFRESH:

                    refreshDeviceList();

                    mHandler.sendEmptyMessageDelayed(MESSAGE_REFRESH, REFRESH_TIMEOUT_MILLIS);

                    break;

                default:

                    super.handleMessage(msg);

                    break;

            }

        }

    };

    public void resume() {

        mHandler.sendEmptyMessage(MESSAGE_REFRESH);

    }

    public void pause() {

        mHandler.removeMessages(MESSAGE_REFRESH);

    }

    private void refreshDeviceList() {

        new AsyncTask<Void, Void, List<UsbSerialPort>>() {

            @Override

            protected List<UsbSerialPort> doInBackground(Void... params) {

                SystemClock.sleep(1000);

                final List<UsbSerialDriver> drivers =

                        UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager);

                final List<UsbSerialPort> result = new ArrayList<UsbSerialPort>();

                for (final UsbSerialDriver driver : drivers) {

                    final List<UsbSerialPort> ports = driver.getPorts();

                    result.addAll(ports);

                }

                return result;

            }

            @Override

            protected void onPostExecute(List<UsbSerialPort> result) {

                mPortList.clear();

                mPortList.addAll(result);

                if (!result.isEmpty()) {

                    mSerialPort = mPortList.get(0);

                    //擷取到一次即可,随後删除消息

                    mHandler.removeMessages(MESSAGE_REFRESH);

                    initPort();

                }

            }

        }.execute((Void) null);

    }

    private void initPort() {

        UsbDeviceConnection connection = mUsbManager.openDevice(mSerialPort.getDriver().getDevice());

        if (connection == null) {

            return;

        }

        try {

            mSerialPort.open(connection);

            //預設參數

            //sPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

            //序列槽調試參數

            mSerialPort.setParameters(38400, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

        } catch (IOException e) {

            try {

                mSerialPort.close();

            } catch (IOException e2) {

                // Ignore.

            }

            mSerialPort = null;

            return;

        }

        onDeviceStateChange();

    }

    public void writeData(String data) {

        if(mSerialPort == null) return;

        try {

            byte[] bytes = StringToBytes.getFCSData(data.getBytes());

            int result = mSerialPort.write(bytes, 1000);

            Toast.makeText(mContext, data + ":" + result, Toast.LENGTH_SHORT).show();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    private void stopIoManager() {

        if (mSerialIoManager != null) {

            mSerialIoManager.stop();

            mSerialIoManager = null;

        }

    }

    private void startIoManager() {

        if (mSerialPort != null) {

            mSerialIoManager = new SerialInputOutputManager(mSerialPort, mListener);

            mExecutor.submit(mSerialIoManager);

        }

    }

    private void onDeviceStateChange() {

        stopIoManager();

        startIoManager();

    }

    private final SerialInputOutputManager.Listener mListener =

            new SerialInputOutputManager.Listener() {

                @Override

                public void onRunError(Exception e) {

                }

                @Override

                public void onNewData(final byte[] data) {

                }

            };

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

在我的Activity中是這樣寫的,就是這樣了。

public class MainActivity extends Activity {

    DeviceManager mManager;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mManager = new DeviceManager(this);

        findViewById(R.id.LightOn).setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                mManager.writeData("LightOn");

            }

        });

    }

    @Override

    protected void onResume() {

        super.onResume();

        mManager.resume();

    }

    @Override

    protected void onPause() {

        super.onPause();

        mManager.pause();

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

注:建議第一次接觸的人,還是先去看看usb-serial-for-android 這個架構,能擷取到序列槽裝置後,再來看看我寫的方法。

5、Demo下載下傳

【點選下載下傳】

原文:https://blog.csdn.net/chang_1134/article/details/68062212