refactored android example

This commit is contained in:
strawmanbobi
2026-01-18 10:32:13 +08:00
parent 58baedfebd
commit 94b7851f6f
19 changed files with 171 additions and 67 deletions

View File

@@ -17,7 +17,6 @@ import java.util.List;
* Revision log:
* 2017-04-06: created by strawmanbobi
*/
@Table(name = "RemoteControl")
@SuppressWarnings("unused")
public class RemoteControl extends Model {

View File

@@ -1,10 +1,23 @@
package net.irext.ircontrol.controller;
import android.content.Context;
import android.util.Log;
import net.irext.ircontrol.controller.implementable.IRemote;
/**
* Filename: ArduinoRemote.java
* Revised: Date: 2026-01-18
* Revision: Revision: 1.0
* <p>
* Description: Remote implementation by Arduino
* <p>
* Revision log:
*2026-01-18: created by strawmanbobi
*/
public class ArduinoRemote implements IRemote {
private static final String TAG = PhoneRemote.class.getSimpleName();
Context mContext;
ArduinoSocket mArduinoSocket;
@@ -15,6 +28,7 @@ public class ArduinoRemote implements IRemote {
@Override
public int irControl(int category, int subCategory, int keyCode) {
Log.d(TAG, "irControl, category = " + category + ", subCategory = " + subCategory + ", keyCode = " + keyCode);
return 0;
}
}

View File

@@ -12,7 +12,13 @@ import java.util.Base64;
/**
* Filename: ArduinoSocket.java
* Description: Handle socket communication with external IR emitter
* Revised: Date: 2026-01-18
* Revision: Revision: 1.0
* <p>
* Description: Communication interface to Arduino
* <p>
* Revision log:
*2026-01-18: created by strawmanbobi
*/
public class ArduinoSocket {
private static final String TAG = ArduinoSocket.class.getSimpleName();
@@ -70,9 +76,7 @@ public class ArduinoSocket {
emitterConn.setKeepAlive(true);
connectionStatus = EMITTER_CONNECTED;
if (callback != null) {
callback.onConnected();
}
onConnected();
BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream()));
String response;
@@ -166,10 +170,23 @@ public class ArduinoSocket {
// Handle control response if needed
}
public static boolean isValidIPv4(String ip) {
if (ip == null) {
return false;
private void onConnected() {
if (callback != null) {
Log.d(TAG, "the emitter is connected");
callback.onConnected();
}
}
private void onResponse(String response) {
Log.d(TAG, "emitter: " + response);
if (response.startsWith(ArduinoSocket.E_RESPONSE_HELLO)) {
processEHello(response);
} else if (response.startsWith(ArduinoSocket.E_RESPONSE_BIN)) {
} else if (response.startsWith(ArduinoSocket.E_RESPONSE_CTRL)) {
processECtrl(response);
} else {
Log.e(TAG, "unexpected response : " + response);
}
return Patterns.IP_ADDRESS.matcher(ip).matches();
}
}

View File

@@ -11,7 +11,17 @@ import java.util.Objects;
import static net.irext.ircontrol.controller.implementable.IRemote.*;
public class ControlUtils {
/**
* Filename: ControlHelper.java
* Revised: Date: 2026-01-18
* Revision: Revision: 1.0
* <p>
* Description: Remote control helper class
* <p>
* Revision log:
*2026-01-18: created by strawmanbobi
*/
public class ControlHelper {
public static int translateKeyCode(int category, int keyCode, ACStatus acStatus) {
int inputKeyCode = 0;

View File

@@ -6,6 +6,16 @@ import net.irext.decode.sdk.IRDecode;
import net.irext.decode.sdk.bean.ACStatus;
import net.irext.ircontrol.controller.implementable.IRemote;
/**
* Filename: PhoneRemote.java
* Revised: Date: 2026-01-18
* Revision: Revision: 1.0
* <p>
* Description: Remote implementation by Android phone
* <p>
* Revision log:
*2026-01-18: created by strawmanbobi
*/
public class PhoneRemote implements IRemote {
private static final String TAG = PhoneRemote.class.getSimpleName();
@@ -23,7 +33,7 @@ public class PhoneRemote implements IRemote {
int []decoded;
StringBuilder debugStr = new StringBuilder();
ACStatus acStatus = new ACStatus();
int inputKeyCode = ControlUtils.translateKeyCode(category, keyCode, acStatus);
int inputKeyCode = ControlHelper.translateKeyCode(category, keyCode, acStatus);
decoded = mIRDecode.decodeBinary(inputKeyCode, acStatus);
for (int i = 0; i < decoded.length; i++) {
@@ -33,7 +43,7 @@ public class PhoneRemote implements IRemote {
}
}
Log.d(TAG, "IR control decoded: " + debugStr);
ControlUtils.transmitIr(mContext, decoded);
ControlHelper.transmitIr(mContext, decoded);
return 0;
}
}

View File

@@ -1,8 +1,15 @@
package net.irext.ircontrol.controller.implementable;
import android.content.Context;
import net.irext.decode.sdk.IRDecode;
/**
* Filename: IRemote.java
* Revised: Date: 2026-01-18
* Revision: Revision: 1.0
* <p>
* Description: IRemote interface
* <p>
* Revision log:
*2026-01-18: created by strawmanbobi
*/
public interface IRemote {
public static final int KEY_POWER = 0;

View File

@@ -11,7 +11,7 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import net.irext.ircontrol.R;
import net.irext.ircontrol.ui.fragment.*;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import net.irext.webapi.model.Brand;
import net.irext.webapi.model.Category;
import net.irext.webapi.model.City;
@@ -22,6 +22,16 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
/**
* Filename: CreateActivity.java
* Revised: Date: 2017-04-22
* Revision: Revision: 1.0
* <p>
* Description: Create remote activity
* <p>
* Revision log:
* 2017-04-22: created by strawmanbobi
*/
@SuppressWarnings("unused")
public class CreateActivity extends AppCompatActivity {
@@ -152,7 +162,7 @@ public class CreateActivity extends AppCompatActivity {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
Log.d(TAG, "handle message " + cmd);
CreateActivity createActivity = mCreateActivity.get();

View File

@@ -19,7 +19,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import net.irext.ircontrol.R;
import net.irext.ircontrol.bean.RemoteControl;
import net.irext.ircontrol.ui.fragment.MainFragment;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -182,7 +182,7 @@ public class MainActivity extends AppCompatActivity {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
Log.d(TAG, "handle message " + cmd);
MainActivity mainActivity = mMainActivity.get();

View File

@@ -9,7 +9,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import net.irext.ircontrol.ui.activity.CreateActivity;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
/**
* Filename: BaseCreateFragment.java
@@ -38,7 +38,7 @@ public abstract class BaseCreateFragment extends Fragment {
public void onBackPressed() {
if (-1 != mFrom) {
MessageUtil.postMessage(mParent.mMsgHandler, mFrom);
MessageUtils.postMessage(mParent.mMsgHandler, mFrom);
}
}

View File

@@ -15,7 +15,7 @@ import net.irext.ircontrol.R;
import net.irext.ircontrol.ui.activity.CreateActivity;
import net.irext.ircontrol.ui.adapter.BrandAdapter;
import net.irext.ircontrol.ui.widget.PullToRefreshListView;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import net.irext.webapi.WebAPICallbacks.ListBrandsCallback;
import net.irext.webapi.model.Brand;
@@ -56,7 +56,7 @@ public class BrandFragment extends BaseCreateFragment {
if (null == mBrands) {
mBrands = new ArrayList<>();
}
MessageUtil.postMessage(mMsgHandler, CMD_REFRESH_BRAND_LIST);
MessageUtils.postMessage(mMsgHandler, CMD_REFRESH_BRAND_LIST);
}
@Override
@@ -115,7 +115,7 @@ public class BrandFragment extends BaseCreateFragment {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Brand brand = (Brand)mBrandAdapter.getItem(position);
mParent.setCurrentBrand(brand);
MessageUtil.postMessage(mParent.mMsgHandler,
MessageUtils.postMessage(mParent.mMsgHandler,
CreateActivity.PAGE_INDEX,
CreateActivity.PAGE_BRAND);
}
@@ -140,7 +140,7 @@ public class BrandFragment extends BaseCreateFragment {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
Log.d(TAG, "handle message " + cmd);
BrandFragment brandFragment = mBrandFragment.get();

View File

@@ -16,14 +16,13 @@ import net.irext.ircontrol.R;
import net.irext.ircontrol.ui.activity.CreateActivity;
import net.irext.ircontrol.ui.adapter.CategoryAdapter;
import net.irext.ircontrol.ui.widget.PullToRefreshListView;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import net.irext.webapi.WebAPICallbacks;
import net.irext.webapi.model.Category;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Filename: CategoryFragment.java
@@ -57,7 +56,7 @@ public class CategoryFragment extends BaseCreateFragment {
if (null == mCategories) {
mCategories = new ArrayList<>();
}
MessageUtil.postMessage(mMsgHandler, CMD_REFRESH_CATEGORY_LIST);
MessageUtils.postMessage(mMsgHandler, CMD_REFRESH_CATEGORY_LIST);
}
@Override
@@ -115,11 +114,11 @@ public class CategoryFragment extends BaseCreateFragment {
Category category = (Category)mCategoryAdapter.getItem(position);
mParent.setCurrentCategory(category);
if (category.getId() != Constants.CategoryID.STB.getValue()) {
MessageUtil.postMessage(mParent.mMsgHandler,
MessageUtils.postMessage(mParent.mMsgHandler,
CreateActivity.PAGE_BRAND,
CreateActivity.PAGE_CATEGORY);
} else {
MessageUtil.postMessage(mParent.mMsgHandler,
MessageUtils.postMessage(mParent.mMsgHandler,
CreateActivity.PAGE_CITY,
CreateActivity.PAGE_CATEGORY);
}
@@ -144,7 +143,7 @@ public class CategoryFragment extends BaseCreateFragment {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
Log.d(TAG, "handle message " + cmd);
CategoryFragment categoryFragment = mCategoryFragment.get();

View File

@@ -16,7 +16,7 @@ import net.irext.ircontrol.R;
import net.irext.ircontrol.ui.activity.CreateActivity;
import net.irext.ircontrol.ui.adapter.CityAdapter;
import net.irext.ircontrol.ui.adapter.OperatorAdapter;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import net.irext.webapi.WebAPICallbacks.ListProvincesCallback;
import net.irext.webapi.WebAPICallbacks.ListCitiesCallback;
@@ -28,7 +28,6 @@ import net.irext.webapi.model.StbOperator;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Filename: CityFragment.java
@@ -72,7 +71,7 @@ public class CityFragment extends BaseCreateFragment {
if (null == mProvinces) {
mProvinces = new ArrayList<>();
}
MessageUtil.postMessage(mMsgHandler, CMD_REFRESH_PROVINCE_LIST);
MessageUtils.postMessage(mMsgHandler, CMD_REFRESH_PROVINCE_LIST);
}
@Override
@@ -93,7 +92,7 @@ public class CityFragment extends BaseCreateFragment {
if (null == mCities) {
mCities = new ArrayList<>();
}
MessageUtil.postMessage(mMsgHandler, CMD_REFRESH_CITY_LIST);
MessageUtils.postMessage(mMsgHandler, CMD_REFRESH_CITY_LIST);
}
@Override
@@ -115,7 +114,7 @@ public class CityFragment extends BaseCreateFragment {
if (null == mOperators) {
mOperators = new ArrayList<>();
}
MessageUtil.postMessage(mMsgHandler, CMD_REFRESH_OPERATOR_LIST);
MessageUtils.postMessage(mMsgHandler, CMD_REFRESH_OPERATOR_LIST);
}
@Override
@@ -147,7 +146,7 @@ public class CityFragment extends BaseCreateFragment {
}
}.start();
} else {
MessageUtil.postMessage(mMsgHandler, CMD_REFRESH_PROVINCE_LIST);
MessageUtils.postMessage(mMsgHandler, CMD_REFRESH_PROVINCE_LIST);
}
}
@@ -235,7 +234,7 @@ public class CityFragment extends BaseCreateFragment {
case LEVEL_OPERATOR:
StbOperator operator = (StbOperator)mOperatorAdapter.getItem(position);
mParent.setCurrentOperator(operator);
MessageUtil.postMessage(mParent.mMsgHandler,
MessageUtils.postMessage(mParent.mMsgHandler,
CreateActivity.PAGE_INDEX,
CreateActivity.PAGE_CITY);
break;
@@ -273,7 +272,7 @@ public class CityFragment extends BaseCreateFragment {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
Log.d(TAG, "handle message " + cmd);
CityFragment cityFragment = mCityFragment.get();

View File

@@ -20,7 +20,7 @@ import net.irext.ircontrol.controller.PhoneRemote;
import net.irext.ircontrol.controller.implementable.IRemote;
import net.irext.ircontrol.ui.activity.ControlActivity;
import net.irext.ircontrol.utils.FileUtils;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import net.irext.ircontrol.utils.ToastUtils;
import java.lang.ref.WeakReference;
@@ -148,11 +148,23 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
}
}
@Override
public void onStop() {
super.onStop();
mArduinoSocket.disconnect();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mArduinoSocket.disconnect();
}
private void getRemote() {
new Thread() {
@Override
public void run() {
MessageUtil.postMessage(mHandler, CMD_GET_REMOTE_CONTROL);
MessageUtils.postMessage(mHandler, CMD_GET_REMOTE_CONTROL);
}
}.start();
}
@@ -175,7 +187,6 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
}
private void onEmitterConnected() {
Log.d(TAG, "the emitter is connected");
mParent.runOnUiThread(() -> {
mBtnConnect.setImageDrawable(AppCompatResources.getDrawable(mParent, R.mipmap.button_unlink));
mVWConnectStatus.setBackgroundColor(Color.parseColor("#3FAFFF"));
@@ -272,7 +283,7 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
ControlFragment controlFragment = mMainFragment.get();
if (cmd == CMD_GET_REMOTE_CONTROL) {

View File

@@ -17,7 +17,7 @@ import net.irext.ircontrol.ui.widget.PullToRefreshListView;
import net.irext.ircontrol.R;
import net.irext.ircontrol.ui.adapter.IndexAdapter;
import net.irext.ircontrol.utils.FileUtils;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import net.irext.webapi.WebAPICallbacks.ListIndexesCallback;
import net.irext.webapi.WebAPICallbacks.DownloadBinCallback;
import net.irext.webapi.model.Brand;
@@ -31,7 +31,6 @@ import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Filename: IndexFragment.java
@@ -82,7 +81,7 @@ public class IndexFragment extends BaseCreateFragment {
if (null == mIndexes) {
mIndexes = new ArrayList<>();
}
MessageUtil.postMessage(mMsgHandler, CMD_REFRESH_INDEX_LIST);
MessageUtils.postMessage(mMsgHandler, CMD_REFRESH_INDEX_LIST);
}
@Override
@@ -101,7 +100,7 @@ public class IndexFragment extends BaseCreateFragment {
public void onDownloadBinSuccess(InputStream inputStream) {
Log.d(TAG, "binary file download successfully");
mBinStream = inputStream;
MessageUtil.postMessage(mMsgHandler, CMD_BIN_FILE_DOWNLOADED);
MessageUtils.postMessage(mMsgHandler, CMD_BIN_FILE_DOWNLOADED);
}
@Override
@@ -168,7 +167,7 @@ public class IndexFragment extends BaseCreateFragment {
}
if (null != mBinStream) {
MessageUtil.postMessage(mMsgHandler, CMD_SAVE_REMOTE_CONTROL);
MessageUtils.postMessage(mMsgHandler, CMD_SAVE_REMOTE_CONTROL);
} else {
Log.e(TAG, "bin file download failed");
}
@@ -245,7 +244,7 @@ public class IndexFragment extends BaseCreateFragment {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mCurrentIndex = (RemoteIndex) mIndexAdapter.getItem(position);
MessageUtil.postMessage(mMsgHandler, CMD_DOWNLOAD_BIN_FILE);
MessageUtils.postMessage(mMsgHandler, CMD_DOWNLOAD_BIN_FILE);
}
});
@@ -269,7 +268,7 @@ public class IndexFragment extends BaseCreateFragment {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
IndexFragment indexFragment = mIndexFragment.get();
switch (cmd) {

View File

@@ -16,7 +16,7 @@ import net.irext.ircontrol.bean.RemoteControl;
import net.irext.ircontrol.ui.activity.MainActivity;
import net.irext.ircontrol.ui.adapter.RemoteControlAdapter;
import net.irext.ircontrol.ui.widget.PullToRefreshListView;
import net.irext.ircontrol.utils.MessageUtil;
import net.irext.ircontrol.utils.MessageUtils;
import java.lang.ref.WeakReference;
import java.util.List;
@@ -79,7 +79,7 @@ public class MainFragment extends Fragment {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
RemoteControl remoteControl = (RemoteControl)mRemoteControlAdapter.getItem(position);
mParent.setCurrentRemoteControl(remoteControl);
MessageUtil.postMessage(mParent.mMsgHandler, MainActivity.CMD_GOTO_CONTROL);
MessageUtils.postMessage(mParent.mMsgHandler, MainActivity.CMD_GOTO_CONTROL);
}
});
return view;
@@ -96,7 +96,7 @@ public class MainFragment extends Fragment {
@Override
public void run() {
mRemoteControls = RemoteControl.listRemoteControls(0, 20);
MessageUtil.postMessage(mHandler, CMD_REFRESH_REMOTE_LIST);
MessageUtils.postMessage(mHandler, CMD_REFRESH_REMOTE_LIST);
}
}.start();
}
@@ -126,7 +126,7 @@ public class MainFragment extends Fragment {
@Override
public void handleMessage(Message msg) {
int cmd = msg.getData().getInt(MessageUtil.KEY_CMD);
int cmd = msg.getData().getInt(MessageUtils.KEY_CMD);
Log.d(TAG, "handle message " + cmd);
MainFragment mainFragment = mMainFragment.get();

View File

@@ -15,7 +15,7 @@ import android.os.Message;
* 2017-04-08: created by strawmanbobi
*/
@SuppressWarnings("unused")
public class MessageUtil {
public class MessageUtils {
public static final String KEY_CMD = "CMD";

View File

@@ -0,0 +1,24 @@
package net.irext.ircontrol.utils;
import android.util.Patterns;
/**
* Filename: MiscUtils.java
* Revised: Date: 2026-01-18
* Revision: Revision: 1.0
* <p>
* Description: Misc utilities
* <p>
* Revision log:
* 2017-04-08: created by strawmanbobi
*/
public class MiscUtils {
public static boolean isValidIPv4(String ip) {
if (ip == null) {
return false;
}
return Patterns.IP_ADDRESS.matcher(ip).matches();
}
}

View File

@@ -27,10 +27,10 @@
#include <cstdint>
// Wi-Fi Configs
#define SECRET_SSID "Maomao的小房子"
#define SECRET_PASS "Maomao121207"
// #define SECRET_SSID "maomao"
// #define SECRET_PASS "20121207"
// #define SECRET_SSID "Maomao的小房子"
// #define SECRET_PASS "Maomao121207"
#define SECRET_SSID "maomao"
#define SECRET_PASS "20121207"
// LED Matrix Definitions
constexpr uint32_t chip[] = {

View File

@@ -32,6 +32,8 @@
#define WIFI_SERVER_PORT (8000)
#define ALIVE_DEBUG_INTERVAL (20 * 1000)
// global variable definitions
constexpr char ssid[] = SECRET_SSID;
constexpr char pass[] = SECRET_PASS;
@@ -70,7 +72,8 @@ void drawIp(const char *ipAddr) {
void printWiFiStatus() {
unsigned long currentMillis = millis();
if (currentMillis - lastStatusCheck >= 10000 && !wifiStatusPrinted) {
if (currentMillis - lastStatusCheck >= ALIVE_DEBUG_INTERVAL) {
IPAddress ip = WiFi.localIP();
if (0 == strcmp(ip.toString().c_str(), "0.0.0.0")) {
lastStatusCheck = currentMillis;
@@ -86,11 +89,13 @@ void printWiFiStatus() {
Serial.print("Signal strength (RSSI): ");
Serial.print(rssi);
Serial.println(" dBm");
drawIp(ip.toString().c_str());
lastStatusCheck = currentMillis;
if (0 == wifiStatusPrinted) {
drawIp(ip.toString().c_str());
wifiStatusPrinted = true;
}
}
}
void setup() {
@@ -112,18 +117,18 @@ void setup() {
matrix.endText(SCROLL_LEFT);
matrix.endDraw();
Serial.println("Wi-Fi started in station mode");
Serial.println("IRext Arduino example started in station mode");
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
if (status == WL_CONNECTED) {
Serial.println("\nConnection Successful!");
Serial.println("\nConnected to Wi-Fi");
server.begin();
}
else {
Serial.print("\nConnection Failed! Status: ");
Serial.print("\nFailed to connect Wi-Fi, status: ");
Serial.println(status);
}
}