【教程】手机远程连接另一台手机的termux进行拍照

目录

被控端手机(termux)

控制端手机


    主要通过MQTT实现通信。图片的上传和显示使用了服务器

    对于没有服务器的同学,可以进入官网领取免费1个月的轻量云服务器云产品免费试用;需要选购的进:轻量应用服务器专场;不清楚怎么操作的可以看教程:腾讯云产品免费试用教程

实现效果:

        当然这只是一个示例,只要能实现手机间的通信,那就可以借助termux-api实现非常多的功能!

被控端手机(termux)

pip换源:

apt update -y
apt upgrade -y
apt install python -y
apt install python-dev -y
apt install clang -y
apt install libffi-dev -y
apt install openssl-dev -y
apt install libxml2-dev libxslt-dev -y
mkdir ~/.pip
touch ~/.pip/pip.conf
nano ~/.pip/pip.conf

写入内容:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple/

termux安装mqtt等库

pip install paho-mqtt requests
apt install imagemagick catimg -y

termux中的Python代码为:

# coding:utf-8
import paho.mqtt.client as pahomqtt
import os
import base64
import requests
import time
import threading
import socket
from queue import Queue

def get_host_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    ip = ''
    try:
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    finally:
        s.close()
    return ip

class MQTT:
    def __init__(self):
        self.CLIENTID = 'redmi8'
        self.MQTTHOST = "xfxuezhang.cn"
        self.MQTTPORT = 1883
        self.USERNAME = 'lh'
        self.PASSWORD = "hualala"
        self.HEARTBEAT = 60
        self.topic_subscribe = f'/mqtt/{self.CLIENTID}'
        self.topic_publish = f'/mqtt/{self.CLIENTID}/send/msg'
        self.topic_publish_image = f'/mqtt/{self.CLIENTID}/send/image'
        self.heart_beat_publish = f'/mqtt/{self.CLIENTID}/heartbeat'
        self.client = pahomqtt.Client()
        self.CloudAllowRun = 1
        self.msg_buffer = Queue()
 
    def get_msg(self):
        if self.msg_buffer.empty():
            return None
        return self.msg_buffer.get()
    
    # MQTT连接回调
    def on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            print("Connected")
            client.subscribe(self.topic_subscribe)
 
    # MQTT接收回调
    def on_message(self, client, userdata, message):
        result = 'ok'
        msg = str(message.payload.decode("utf-8")).strip()
        print("Received message: " + msg)
        self.msg_buffer.put(msg)
        
  
    def remove_image(self, path="a.png"):
        url = 'http://xfxuezhang.cn/web/picture/remove_file.php?name='+path
        if os.path.exists(path):
            os.remove(path)
        return requests.get(url).text
 
    def upload_image(self, path="a.png"):
        result = None
        try:
            url = 'http://xfxuezhang.cn/web/picture/upload_file.php'
            os.popen(f'convert {path} -resize 200x150 {path}')
            filename = path.split('/')[-1]
            files = {"file": (filename, open(path, "rb"), "image/png")}
            response = requests.post(url, files=files)
            print(response.text)
            result = response.json()['data']
        except Exception as e:
            print(e)
        return result
 
 
    def convert_image(self, path="a.png"):
        os.popen(f'convert {path} -resize 200x150 {path}')
        # 从文件中读取图片并将其转换为二进制数据
        with open(path, "rb") as f:
            image_bytes = f.read()
        # 将二进制数据编码为base64字符串
        image_base64 = base64.b64encode(image_bytes).decode("utf-8")
        return image_base64
 
 
    def heart_beat(self):
        msg = 'ip: ' + get_host_ip()
        print(f'>> 心跳信息: {msg}')
        try:
            self.client.publish(topic=self.heart_beat_publish, payload=msg, qos=0)
        except Exception as e:
            print(e)
            
    def mqtt(self):
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message
        self.client.username_pw_set(self.USERNAME, self.PASSWORD)
        try:
            self.client.connect(self.MQTTHOST, self.MQTTPORT, self.HEARTBEAT)
            # self.client.loop_forever() # 阻塞方式
            self.client.loop_start()     # 线程方式
        except:
            pass
 
    def publish(self, topic, msg, qos=0):
        self.client.publish(topic=topic, payload=msg, qos=qos)
 
 
if __name__ == '__main__':
    mqtt = MQTT()
    while True:
        try:
            mqtt.mqtt()
            break
        except Exception as e:
            print('异常,5s后重试=>' + str(e))
            time.sleep(5)
    print('>> MQTT 启动成功')
    
    while True:
        msg = mqtt.get_msg()
        if not msg:
            # 没有消息要处理时,定时上报心跳
            mqtt.heart_beat()
            time.sleep(1)
            continue
        # 收到消息
        if msg.startswith('cmd:img'):
            _, cmd, path = msg.split(' ')
            print('>> 图片路径:', path)
            if cmd == 'upload':
                img = mqtt.upload_image(path)
                if img:
                    mqtt.publish(topic=mqtt.topic_publish_image, msg=img)
                    result = 'upload ok'
                else:
                    result = 'upload fail'
            elif cmd == 'remove':
                mqtt.remove_image(path)
                result = 'remove ok'
        else:
            # 执行本地cmd命令,并将结果保存到变量result中
            result = os.popen(msg).read().strip() or 'complete'
        print(">> 指令结果: " + result)
        mqtt.publish(topic=mqtt.topic_publish, msg=result)

        

运行记录:

控制端手机

        另一台控制端的手机上安装“MQTT Dashboard”,并添加一些组件,其中的主题根据上面的代码来填。实现效果:

MQTT Dashboard 中导入上面所示的界面配置

{"tiles":[{"broker_id":1,"color":-8604862,"compact_layout":false,"confirm":false,"customize_output":false,"enable_pub":false,"icon":"device_vec_home_account","last_update":1688190731101,"name":"执行结果","notificationMessage":"","notificationTitle":"","notifyOnChange":false,"output_template":"","paintBackground":true,"payloadIsJson":false,"payload_path":"","position":0,"qos":0,"retain":false,"show_as_shortcut":false,"tile_details":{},"tile_type":3,"timestamp_path":"","topic":"/mqtt/redmi8/send/msg","topic_pub":"","tunables":{"text_postfix":"","text_prefix":""},"uid":4,"value":""},{"broker_id":1,"color":-16023485,"compact_layout":true,"confirm":true,"customize_output":false,"enable_pub":true,"icon":"mdes_ico_camera_alt","last_update":0,"name":"前置拍照","notificationMessage":"","notificationTitle":"","notifyOnChange":false,"output_template":"","paintBackground":true,"payloadIsJson":false,"payload_path":"","position":1,"qos":0,"retain":false,"show_as_shortcut":false,"tile_details":{},"tile_type":2,"timestamp_path":"","topic":"","topic_pub":"/mqtt/redmi8","tunables":{"click_payload":"termux-camera-photo -c 1 a.png"},"uid":1,"value":""},{"broker_id":1,"color":-538816,"compact_layout":true,"confirm":true,"customize_output":false,"enable_pub":true,"icon":"mdes_ico_collections","last_update":0,"name":"获取照片","notificationMessage":"","notificationTitle":"","notifyOnChange":false,"output_template":"","paintBackground":true,"payloadIsJson":false,"payload_path":"","position":2,"qos":0,"retain":false,"show_as_shortcut":false,"tile_details":{},"tile_type":2,"timestamp_path":"","topic":"","topic_pub":"/mqtt/redmi8","tunables":{"click_payload":"cmd:img upload a.png"},"uid":2,"value":""},{"broker_id":1,"color":-2818048,"compact_layout":true,"confirm":true,"customize_output":false,"enable_pub":true,"icon":"mdes_ico_delete_forever","last_update":0,"name":"删除照片","notificationMessage":"","notificationTitle":"","notifyOnChange":false,"output_template":"","paintBackground":true,"payloadIsJson":false,"payload_path":"","position":3,"qos":0,"retain":false,"show_as_shortcut":false,"tile_details":{},"tile_type":2,"timestamp_path":"","topic":"","topic_pub":"/mqtt/redmi8","tunables":{"click_payload":"cmd:img remove a.png"},"uid":3,"value":""},{"broker_id":1,"color":-16540699,"compact_layout":true,"confirm":true,"customize_output":false,"enable_pub":true,"icon":"device_vec_human_greeting","last_update":0,"name":"自定义指令","notificationMessage":"","notificationTitle":"","notifyOnChange":false,"output_template":"","paintBackground":true,"payloadIsJson":false,"payload_path":"","position":4,"qos":0,"retain":false,"show_as_shortcut":false,"tile_details":{},"tile_type":2,"timestamp_path":"","topic":"","topic_pub":"/mqtt/redmi8","tunables":{"click_payload":""},"uid":5,"value":""},{"broker_id":1,"color":-5792882,"compact_layout":false,"confirm":false,"customize_output":false,"enable_pub":true,"icon":"mdes_ico_filter","last_update":1688190953875,"name":"照片显示","notificationMessage":"","notificationTitle":"","notifyOnChange":false,"output_template":"","paintBackground":true,"payloadIsJson":false,"payload_path":"","position":100,"qos":0,"retain":false,"show_as_shortcut":false,"tile_details":{},"tile_type":9,"timestamp_path":"","topic":"/mqtt/redmi8/send/image","topic_pub":"","tunables":{"auto_refresh_image":"true","refresh_interval":"10"},"uid":6,"value":""}],"groups":[],"groupsTileJoin":[]}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小锋学长生活大爆炸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值