使用MQTT远程登录android

写作目的

公司是做楼宇对讲主机设备,设备端运行的是安卓系统,为了远程方便调试设备(如人在深圳控制一台在北京的设备),特做了个远程登录android的小系统,以此记录。

环境介绍

安卓主板一块,一台公网服务器,一台PC

最终效果展示

启动服务器,-p设置端口号为1888
这是服务端启动程序

PC端,使用命令./msgsps_pub -i ens33 -t 76000c885342,登录了一台mac地址为76:00:0c:88:53:42的设备

PC端控制程序
设备端信息
android设备信息

原理介绍

一、 下载MQTT源码

我这里下载的是1.5.1版本,当然也可以尝试下载其他版本

二、源码介绍

源码分为三大块,
1.服务端源码(无需改动,编译后好放入服务器端运行),
2.pub端源码(需要写,这是放在PC端的程序)
3.sub端源码(需要写并移植,这是放在安卓端的程序)
pub源码
/* This provides a crude manner of testing the performance of a broker in messages/s. */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <mosquitto.h>

#include <msgsps_common.h>

static bool run = true;
static int message_count = 0;
static struct timeval start, stop;



void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{

	//printf("msg->payload = %s\n",msg->payload);


	if(msg == NULL || msg->payload == NULL){
		return;
	}
	char oppositeAddr[32] = {0};
	char localAddr[32] = {0};
	char cmdtype[32] = {0};
	int reply = -1;
	int cmdid = -1;
	int ret;
	
	char *cjsonBuf;
	int msglen = strlen(msg->payload);
	FILE* cmdfp = NULL; 
	char *message  = (char *)malloc(msglen);
	if(message == NULL){
		return ;
	}
	memset(message,0,msglen);
	
	ret =  getIntFormCjson(msg->payload ,"cmdid",&cmdid);
	if(ret == 0){
		//printf("cmdid = %d\n",cmdid);
	}
	ret =  getStrFormCjson(msg->payload ,"oppositeAddr",oppositeAddr,sizeof(oppositeAddr));
	if(ret > 0){
		//printf("oppositeAddr = %s\n",oppositeAddr);
	}
	
	ret =  getStrFormCjson(msg->payload ,"localAddr",localAddr,sizeof(localAddr));
	if(ret > 0){
		//printf("localAddr = %s\n",localAddr);
	}
	ret =  getIntFormCjson(msg->payload ,"reply",&reply);
	if(ret == 0){
		//printf("reply = %d\n",reply);
	}
	ret =  getStrFormCjson(msg->payload ,"cmdtype",cmdtype,sizeof(cmdtype));
	if(ret > 0){
		//printf("cmdtype = %s\n",cmdtype);
	}
	ret =  getStrFormCjson(msg->payload ,"message",message,msglen);
	if(ret > 0){
		printf("\n[\n%s]\n",message);
	}

//	mosquitto_loop_stop(mosq, true);
//	mosquitto_destroy(mosq);
//	mosquitto_lib_cleanup();

	

}


void my_connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
	printf("connect succeed!\n");
	gettimeofday(&start, NULL);
}

void my_disconnect_callback(struct mosquitto *mosq, void *obj, int result)
{
	run = false;
}

void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
{
	message_count++;
	if(message_count == MESSAGE_COUNT){
		gettimeofday(&stop, NULL);
		mosquitto_disconnect((struct mosquitto *)obj);
	}
}

int main(int argc, char *argv[])
{
	struct mosquitto *mosq;
	int i;
	double dstart, dstop, diff;
	uint8_t *buf;

		

	char mac[18] = {0};
	char devid[32] = {0};
	char mosid[64] = {0};
	int mid = 0;
	char ethname[8] ={0};
	char oppositeMac[16] = {0};

	if(argc < 5){
		printf("[-t [opposite mac] \n");
		printf("[-i [ethX] \n");
		printf("[-i eth0 -t B44B16101010] \n");
		return -1;
	}

	for(i = 0; i <argc ;i ++){
		if(strcmp(argv[i],"-i") == 0){
			strcpy(ethname,argv[i+1]);

		}
		if(strcmp(argv[i],"-t") == 0){
			strcpy(oppositeMac,argv[i+1]);
		}
	}
	if(ethname[0] == 0 || oppositeMac[0] == 0){
		printf("[-t [opposite mac] \n");
		printf("[-i [ethX] \n");
		printf("[-i eth0 -t B44B16101010] \n");
		return -1;
	}

	

	getDevMacaddr(ethname, mac, 0);
	sprintf(devid,"%s_c",mac);
	mosquitto_lib_init();
	snprintf(mosid, sizeof(mosid), "msgps_pub_%d", getpid());
	mosq = mosquitto_new(mosid, true, NULL);
	mosquitto_connect_callback_set(mosq, my_connect_callback);
	mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
	mosquitto_publish_callback_set(mosq, my_publish_callback);

	mosquitto_message_callback_set(mosq, my_message_callback);

	mosquitto_connect(mosq, HOST, PORT, 600);
	
	mosquitto_subscribe(mosq, &mid, devid, SUB_QOS);
	
	mosquitto_loop_start(mosq);

	char cjsonBuf[1024] = {0};
	char inputBuf[1024] ={0};
	char ch;
	for(;;){
		memset(cjsonBuf,0,sizeof(cjsonBuf));
		memset(inputBuf,0,sizeof(inputBuf));
		
		gets(inputBuf);
		if(strlen(inputBuf) <=0){

			continue;
		}

		if(strcmp(inputBuf,"exit") == 0){
			break;
		}

		
		createCjsonCmd(cjsonBuf, sizeof(cjsonBuf), 999, 1, oppositeMac, devid, "script", inputBuf);
		mosquitto_publish(mosq, NULL,  oppositeMac, strlen(cjsonBuf), cjsonBuf, PUB_QOS, false);
	

	}
	
		
	mosquitto_loop_stop(mosq, true);

	mosquitto_destroy(mosq);
	mosquitto_lib_cleanup();

	return 0;
}

sub源码
/* This provides a crude manner of testing the performance of a broker in messages/s. */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include<errno.h>

#include <signal.h>

#include <sys/time.h>
#include <unistd.h>
#include <mosquitto.h>

#include <log/log.h>
#include <msgsps_common.h>
#include "tools_common.h"
#include <cutils/log.h>


#define LOG_TAG "WB-A8HardWare-MQTT"

#define LOGE(...)  ALOGE(__VA_ARGS__)
#define LOGD(...)  ALOGD(__VA_ARGS__)
#define LOGI(...)  ALOGI(__VA_ARGS__)
#define LOGW(...)  ALOGW(__VA_ARGS__)
static bool run = true;
static int message_count = 0;
static struct timeval start, stop;



void my_connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
	LOGD("rc: %d\n", rc);
}

void my_disconnect_callback(struct mosquitto *mosq, void *obj, int result)
{
	run = false;
}
void alarm_hander(int sig){

	LOGD("timeou  =%d\n!",sig);
}


static int  mypopen(const char*cmd,char *recvBuf,int len ,int timeout){
    //管道文件描述符
    int pfd[2];
	int ret;
	int readLen = 0;
    if(pipe(pfd)!=0){
        LOGD("error: %s\n",strerror(errno));
        return -1;
    }
    //创建子进程
    pid_t  pid=fork();
    if(pid==0){
        close(pfd[0]); 
         //重定向 标准输出 和标准错误输出 到 写管道
		close(STDOUT_FILENO);
	    close(STDERR_FILENO);
		fcntl(pfd[1],F_DUPFD);
		fcntl(pfd[1],F_DUPFD,2);
        execl("/system/bin/sh","sh","-c",cmd,NULL);
		close(pfd[1]); 
        exit(0);
    }
    //关闭写管道
    close(pfd[1]);
	//wait(0); 防止阻塞,此处不等待

   	//设置管道成非阻塞模式
   	
	ret = fcntl(pfd[0], F_SETFL, O_NONBLOCK);
	if (ret != 0) {
		goto fail0;
	}
	
	for(;;){
					struct timeval selcet_tv;
					fd_set fds;
					FD_ZERO(&fds);
					FD_SET( pfd[0], &fds);
					selcet_tv.tv_sec = timeout;
					selcet_tv.tv_usec = 1000;
					do {
						ret = select(pfd[0] + 1, &fds, 0, 0, &selcet_tv);
					} while (ret == -1 && errno == EINTR);

					switch (ret) {
						case 0:
							LOGD("read timeout!\n");
							close(pfd[0]);
							
							return readLen;
						case -1:
							LOGD("fail to select!\n");
						break;
						default: 
							ret = read(pfd[0], recvBuf + readLen, len - readLen);
							if(ret <=0){
								close(pfd[0]);
								
								return readLen;
							}
							readLen += ret;
						}
  }
  
	fail0:
		return -1;
}

































void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{

	if(msg == NULL || msg->payload == NULL){
		return;
	}
	#define MAX_LEN (512*1024)
	char oppositeAddr[32] = {0};
	char localAddr[32] = {0};
	char cmdtype[32] = {0};
	int reply = -1;
	int cmdid = -1;
	int ret;

	char *cjsonBuf;
	int msglen = strlen(msg->payload);
	FILE* cmdfp = NULL; 
	char *message  = (char *)malloc(msglen);
	if(message == NULL){
		return ;
	}
	memset(message,0,msglen);


	ret =  getIntFormCjson(msg->payload ,"cmdid",&cmdid);
	if(ret == 0){
		LOGD("cmdid = %d\n",cmdid);
	}
	ret =  getStrFormCjson(msg->payload ,"oppositeAddr",oppositeAddr,sizeof(oppositeAddr));
	if(ret > 0){
		LOGD("oppositeAddr = %s\n",oppositeAddr);
	}
	
	ret =  getStrFormCjson(msg->payload ,"localAddr",localAddr,sizeof(localAddr));
	if(ret > 0){
		LOGD("localAddr = %s\n",localAddr);
	}
	ret =  getIntFormCjson(msg->payload ,"reply",&reply);
	if(ret == 0){
		LOGD("reply = %d\n",reply);
	}
	ret =  getStrFormCjson(msg->payload ,"cmdtype",cmdtype,sizeof(cmdtype));
	if(ret > 0){
		LOGD("cmdtype = %s\n",cmdtype);
	}
	ret =  getStrFormCjson(msg->payload ,"message",message,msglen);
	if(ret > 0){
		LOGD("message = %s\n",message);
	}

	if(strcmp(cmdtype,"script")  == 0){	

		if(reply){
			int len = 0;
			
			char *fileStr = malloc(MAX_LEN);
			char lineStr[MAX_LEN/100] = {0};
			memset(fileStr,0,MAX_LEN);
		
			len = mypopen(message,fileStr,MAX_LEN,2);
			if(len < 0){
				len = 0;
			}
			cjsonBuf = (char *)malloc(MAX_LEN+CJSON_HEAD_LEN);
			memset(cjsonBuf,0,MAX_LEN+CJSON_HEAD_LEN);	
			createCjsonCmd(cjsonBuf,MAX_LEN+CJSON_HEAD_LEN,cmdid, 0,localAddr,oppositeAddr,"ack",fileStr);
			LOGD("sendcjson = %s \n",cjsonBuf);
			mosquitto_publish(mosq, NULL, localAddr, MAX_LEN+ CJSON_HEAD_LEN ,cjsonBuf, PUB_QOS, false);
			free(fileStr);
			free(cjsonBuf);
		}
		
	}else if(strcmp(cmdtype,"login")  == 0){

		if(reply){
			cjsonBuf = (char *)malloc(CJSON_HEAD_LEN);
			memset(cjsonBuf,0,CJSON_HEAD_LEN);	
			createCjsonCmd(cjsonBuf,CJSON_HEAD_LEN,cmdid, 0,localAddr,oppositeAddr,"ack","login succeed");
			//LOGD("cjsonBuf = %s\n",cjsonBuf);
			LOGD("sendcjson = %s\n",cjsonBuf);
			mosquitto_publish(mosq, NULL, localAddr, strlen(cjsonBuf) + 1,cjsonBuf, PUB_QOS, false);
			free(cjsonBuf);
		}		
	}

fail0:
	free(message);

}



static int getHostAndPort(char *host,unsigned short *port){
	FILE* popenfp = NULL; 
	char buf[128];

	
	popenfp = popen("getprop | grep sys.mqtt_server_ip | cut -d ':' -f 2 |cut -d '[' -f 2 | cut -d ']' -f -1", "r"); //执行脚本并返回
	if(popenfp == NULL){
		return -1;
	}
	memset(buf,0,sizeof(buf));
	if(fgets(buf, sizeof(buf), popenfp) == NULL  || (strlen(buf)<= 0 )){
		return -1;
	}
	buf[strlen(buf)-1] = 0;//去掉最后一个字符
	LOGD("buf = %s\n",buf);
	strcpy(host,buf);
	pclose(popenfp);

	popenfp = popen("getprop | grep sys.mqtt_server_port | cut -d ':' -f 2 |cut -d '[' -f 2 | cut -d ']' -f -1", "r"); //执行脚本并返回
	if(popenfp == NULL){
		return -1;
	}
	memset(buf,0,sizeof(buf));
	if(fgets(buf, sizeof(buf), popenfp) == NULL  || (strlen(buf)<= 0 )){
		return -1;
	}
	buf[strlen(buf)-1] = 0;
	LOGD("buf = %s\n",buf);
	*port = atoi(buf);

	LOGD("port = %d\n",*port);
	pclose(popenfp);

	
	return 0;
}

int main(int argc, char *argv[])
{
	
	double dstart, dstop, diff;
	int mid = 0;
	char id[50];
	struct mosquitto *mosq;
	int ret;

	char mac[18] = {0};
	char serverHost[32] = {0};
	unsigned short serverPort;
	
  	while ( getDevMacaddr("eth0", mac, 1) != 0){
		sleep(1);
	}
	
	mosquitto_lib_init();
	snprintf(id, 50, "msgps_sub_%d", getpid());
	mosq = mosquitto_new(id, true, NULL);
	mosquitto_connect_callback_set(mosq, my_connect_callback);
	mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
	mosquitto_message_callback_set(mosq, my_message_callback);

	if( getHostAndPort(serverHost,&serverPort) < 0){
		strcpy(serverHost,HOST);
		serverPort = PORT;
	}
	LOGD("serverHost:%s serverPort:%d mac:%s\n",serverHost,serverPort,mac);
	for(;;){
		ret =  mosquitto_connect(mosq, serverHost, serverPort, 600);
		LOGD("mosquitto_connect :%d\n",ret);
		if(ret == 0){
			break;
		}
		sleep(1);
	}
	

	mosquitto_subscribe(mosq, &mid, mac, SUB_QOS);

	mosquitto_loop_forever(mosq, -1, 1);

	mosquitto_destroy(mosq);
	mosquitto_lib_cleanup();


	return 0;
}

三、实现原理

在这里插入图片描述

设备端和PC端都以MAC为订阅ID,PC端通过MQTT发送数据到指定的ID上,设备端收到数据后,调用execl执行脚本,并将执行的结果返回给PC端
(不明白处可留言,或加我微信gddw1954讨论)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值