树莓派实现自己的Qt HTTPserver

来源:互联网 发布:java 工作流引擎有哪些 编辑:程序博客网 时间:2024/06/04 19:22

1. 目标

本文以树莓派为硬件,搭建一个本地的httpserver,用于产品中的各种测试。树莓派有了httpserver后,可以跨平台访问,实现了跨平台访问硬件的目标。

2. 清单

这里列举所需要的清单:

  • 2016-9-28 jessie-lite树莓派系统镜像
  • Qt5+boost+opencv
  • xvfb,实现后台运行带窗口的界面
  • daemontool管理后台服务器
  • wifi-access-point脚本,一键设置树莓派为wifi热点

3. 步骤

上述的开发环境,我已将他们全部集成到一个shell脚本中,可在httpserver下,可以一键设置好开发环境。:

1. 配置开发环境
#!/bin/bash## This version uses September 2016 rpi jessie image, please use this image#if [ "$EUID" -ne 0 ]    then echo "Must be root"    exitfiif [[ $# -lt 1 ]];     then echo "You need to pass a password!"    echo "Usage:"    echo "sudo $0 yourChosenPassword [apName]"    exitfiAPPASS="$1"APSSID="rPi3"if [[ $# -eq 2 ]]; then    APSSID=$2fiapt-get remove --purge hostapd -yapt-get install hostapd dnsmasq -ycat > /etc/systemd/system/hostapd.service <<EOF[Unit]Description=Hostapd IEEE 802.11 Access PointAfter=sys-subsystem-net-devices-wlan0.deviceBindsTo=sys-subsystem-net-devices-wlan0.device[Service]Type=forkingPIDFile=/var/run/hostapd.pidExecStart=/usr/sbin/hostapd -B /etc/hostapd/hostapd.conf -P /var/run/hostapd.pid[Install]WantedBy=multi-user.targetEOFcat > /etc/dnsmasq.conf <<EOFinterface=wlan0dhcp-range=10.0.0.2,10.0.0.5,255.255.255.0,12hEOFcat > /etc/hostapd/hostapd.conf <<EOFinterface=wlan0hw_mode=gchannel=10auth_algs=1wpa=2wpa_key_mgmt=WPA-PSKwpa_pairwise=CCMPrsn_pairwise=CCMPwpa_passphrase=$APPASSssid=$APSSIDEOFsed -i -- 's/allow-hotplug wlan0//g' /etc/network/interfacessed -i -- 's/iface wlan0 inet manual//g' /etc/network/interfacessed -i -- 's/    wpa-conf \/etc\/wpa_supplicant\/wpa_supplicant.conf//g' /etc/network/interfacescat >> /etc/network/interfaces <<EOF    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf# Added by rPi Access Point Setupallow-hotplug wlan0iface wlan0 inet static    address 10.0.0.1    netmask 255.255.255.0    network 10.0.0.0    broadcast 10.0.0.255EOFecho "denyinterfaces wlan0" >> /etc/dhcpcd.confsystemctl enable hostapdsudo apt-get install qt5-default  sudo apt-get install qtcreatorsudo apt-get install libqt5svg5* libqt5webkit5* libqt5serialport5*sudo apt-get install qtcreatorsudo apt-get install libboost1.50-allsudo apt-get install xvfbsudo apt-get install daemontools daemontools-runecho "All done! Please reboot"
2. 设置后台运行脚本

使用xvfb,可以在没有桌面系统的情况下,照样调用Qt的一些窗口库(由于应用中,要用到一些带窗口的类的功能)。调用execut.sh脚本如下:

#!/bin/shecho "Execut the service by daemontools"echo "Next will start the linebot"cd /home/pi/raspberrylinebot/build/echo "Really exec the linebot"sudo xvfb-run --server-args="-screen 0 1024x768x24" ./LineBotecho "The linebot has finish started!"

下一步就是设置daemontools来对后台程序进行管理。当后台的Qt应用程序自己当掉了,daemontools会自动在5秒后重启应用。

sudo mkdir -p /service/yourapp-sericesudo vi /service/youapp-service/runsudo chmod 755 /service/youapp-service/runcd /etc/service/sudo ln -s /service/yourapp-service  . 

在/service/youapp-service/run中,run是一个shell脚本,在这里调用使用exec来调用上一步骤中的execut.sh脚本。

3. 备份你的系统

使用备份脚本:

#!/bin/bashVERSION=1.5# Version 1.5   2016/09/09#   * Remove any leading /dev/ from dest disk.#   * Warn dest disk may be a partition if it ends with a digit.# Version 1.4   2016/03/23#   * Use -F on mkfs.ext4 and avoid the question.# Version 1.3   2016/03/16#   * don't > /dev/null for the mkfs.ext4 since mkfs can ask a question# Version 1.2   2015/02/17#   * add -x option#   * tweak some echo messages# Version 1.1   2015/02/16#   * Do not include dphys swapfile in the clone.#   * Add a missing -s flag to one of the parted commands.#   * Dump parted stderr to /dev/null since it now complains about destination#       disk partitions ending outside of disk before I get chance to resize#       the partitions.#   * Strip trailing s from PART_START - (fdisk now doesn't seem to accept...)#PGM=`basename $0`RSYNC_OPTIONS="--force -rltWDEgopt"# List of extra dirs to create under /mnt.OPTIONAL_MNT_DIRS="clone mnt sda sdb rpi0 rpi1"# Where to mount the disk filesystems to be rsynced.CLONE=/mnt/cloneCLONE_LOG=/var/log/$PGM.logHOSTNAME=`hostname`SRC_BOOT_PARTITION_TYPE=`parted /dev/mmcblk0 -ms p | grep "^1" | cut -f 5 -d:`SRC_ROOT_PARTITION_TYPE=`parted /dev/mmcblk0 -ms p | grep "^2" | cut -f 5 -d:`if [ `id -u` != 0 ]then    echo -e "$PGM needs to be run as root.\n"    exit 1fiif ! rsync --version > /dev/nullthen    echo -e "\nOoops! rpi-clone needs the rsync program but cannot find it."    echo "Make sure rsync is installed:"    echo "    $ sudo apt-get update"    echo -e "    $ sudo apt-get install rsync\n"    exit 0fiif test -e /sbin/fsck.vfatthen    HAVE_FSCK_VFAT="yes"else    echo "[Note] fsck.vfat was not found."    echo "It is recommended to install dosfstools:"    echo "    $ sudo apt-get update"    echo "    $ sudo apt-get install dosfstools"fiusage()    {    echo ""    echo "usage: $PGM sdN {-f|--force-initialize} {-v|--verbose} {-x}"    echo "    Example:  $PGM sda"    echo "    -v - list all files as they are copied."    echo "    -f - force initialize the destination partitions"    echo "    -x - use set -x for very verbose bash shell script debugging"    echo ""    echo "    Clone (rsync) a running Raspberry Pi file system to a destination"    echo "    SD card 'sdN' plugged into a Pi USB port (via a USB card reader)."    echo "    $PGM can clone the running system to a new SD card or can"    echo "    incrementally rsync to existing backup Raspberry Pi SD cards."    echo ""    echo "    If the destination SD card has an existing $SRC_BOOT_PARTITION_TYPE partition 1 and a"    echo "    $SRC_ROOT_PARTITION_TYPE partition 2, $PGM assumes (unless using the -f option)"    echo "    that the SD card is an existing backup with the partitions"    echo "    properly sized and set up for a Raspberry Pi.  All that is needed"    echo "    is to mount the partitions and rsync them to the running system."    echo ""    echo "    If these partitions are not found (or -f), then $PGM will ask"    echo "    if it is OK to initialize the destination SD card partitions."    echo "    This is done by a partial 'dd' from the running booted device"    echo "    /dev/mmcblk0 to the destination SD card /dev/sdN followed by a"    echo "    fdisk resize and mkfs.ext4 of /dev/sdN partition 2."    echo "    This creates a completed $SRC_BOOT_PARTITION_TYPE partition 1 containing all boot"    echo "    files and an empty but properly sized partition 2 rootfs."    echo "    The SD card  partitions are then mounted and rsynced to the"    echo "    running system."    echo ""    echo "    The SD card destination partitions will be mounted on $CLONE."    echo "    A log will be written to $CLONE_LOG."    echo "    It's better to avoid running other disk writing programs"    echo "    when running $PGM."    echo ""    echo "    Version $VERSION"    exit 0    }VERBOSE=offwhile [ "$1" ]do    case "$1" in        -v|--verbose)            VERBOSE=on            RSYNC_OPTIONS=${RSYNC_OPTIONS}v            ;;        -f|--force-initialize)            FORCE_INITIALIZE=true            ;;        -x)            set -x            ;;        -h|--help)            usage            ;;        *)            if [ "$DST_DISK" != "" ]            then                echo "Bad args"                usage            fi            DST_DISK=$1            ;;    esac    shiftdoneif [ "$DST_DISK" = "" ]then    usage    exit 0fi# Remove leading /dev/DIR=`expr substr $DST_DISK 1 5`if [ "$DIR" == "/dev/" ]then    DST_DISK=${DST_DISK#/dev/}fiif ! cat /proc/partitions | grep -q $DST_DISKthen    echo "Destination disk '$DST_DISK' does not exist."    echo "Plug the destination SD card into a card reader connected to a"    echo "USB port.  If it does not show up  as '$DST_DISK', then do a"    echo -e "'cat /proc/partitions' to see where it might be.\n"    exit 0fiCHK_DISK=`cat /proc/partitions | grep -m 1 $DST_DISK`D=${CHK_DISK: -1}if [ "$D" -eq "$D" ] 2>/dev/nullthen    echo "  The target disk you entered, $DST_DISK, ends with a digit and this"    echo "  may mean you have given a partition name instead of a disk name."    echo "  For example, if you want to clone to a disk sda,"    echo "  specify sda and not one of its partition names like sda1 or sda2."    echo -n "Do you want to continue anyway? (yes/no):"    read resp    if [ "$resp" != "y" ] && [ "$resp" != "yes" ]    then        echo ""        exit 0    fifiunmount_or_abort()    {    echo -n "Do you want to unmount $1? (yes/no): "    read resp    if [ "$resp" = "y" ] || [ "$resp" = "yes" ]    then        if ! umount $1        then            echo "Sorry, $PGM could not unmount $1."            echo -e "Aborting!\n"            exit 0        fi    else        echo -e "Aborting!\n"        exit 0    fi    }DST_ROOT_PARTITION=/dev/${DST_DISK}2DST_BOOT_PARTITION=/dev/${DST_DISK}1# Check that none of the destination partitions are busy (mounted).#DST_ROOT_CURMOUNT=`fgrep "$DST_ROOT_PARTITION " /etc/mtab | cut -f 2 -d ' ' `DST_BOOT_CURMOUNT=`fgrep "$DST_BOOT_PARTITION " /etc/mtab | cut -f 2 -d ' ' `if [ "$DST_ROOT_CURMOUNT" != "" ] || [ "$DST_BOOT_CURMOUNT" != "" ]then    echo "A destination partition is busy (mounted).  Mount status:"    echo "    $DST_ROOT_PARTITION:  $DST_ROOT_CURMOUNT"    echo "    $DST_BOOT_PARTITION:  $DST_BOOT_CURMOUNT"    if [ "$DST_BOOT_CURMOUNT" != "" ]    then        unmount_or_abort $DST_BOOT_CURMOUNT    fi    if [ "$DST_ROOT_CURMOUNT" != "" ]    then        unmount_or_abort $DST_ROOT_CURMOUNT    fifiTEST_MOUNTED=`fgrep " $CLONE " /etc/mtab | cut -f 1 -d ' ' `if [ "$TEST_MOUNTED" != "" ]then    echo "This script uses $CLONE for mounting filesystems, but"    echo "$CLONE is already mounted with $TEST_MOUNTED."    unmount_or_abort $CLONE fiif [ ! -d $CLONE ]then    MNT_MOUNT=`fgrep " /mnt " /etc/mtab | cut -f 1 -d ' ' `    if [ "$MNT_MOUNT" = "" ]    then        mkdir $CLONE    else        echo "$MNT_MOUNT is currently mounted on /mnt."        unmount_or_abort /mnt        mkdir $CLONE    fifi# Borrowed from do_expand_rootfs in raspi-configexpand_rootfs()    {    # Get the starting offset of the root partition    # (with Jessie's parted, now need to strip trailing 's' from PART_START)    PART_START=$(parted /dev/mmcblk0 -ms unit s p  \            | grep "^2" | cut -f 2 -d: | cut -f 1 -d s)    [ "$PART_START" ] || return 1    # Return value will likely be error for fdisk as it fails to reload the    # partition table because the root fs is mounted    fdisk /dev/$DST_DISK > /dev/null <<EOFpd2np2$PART_STARTpwqEOF    }# =========== Disk Setup and Checks ===========## Check that destination partitions are the right type.#DST_BOOT_PARTITION_TYPE=`parted /dev/$DST_DISK -ms p 2>/dev/null \        | grep "^1" | cut -f 5 -d:`DST_ROOT_PARTITION_TYPE=`parted /dev/$DST_DISK -ms p 2>/dev/null \        | grep "^2" | cut -f 5 -d:`CLONE_MODE="rsync modified files to existing $DST_DISK file systems"if [ "$DST_BOOT_PARTITION_TYPE" != "$SRC_BOOT_PARTITION_TYPE" ] || \   [ "$DST_ROOT_PARTITION_TYPE" != "$SRC_ROOT_PARTITION_TYPE" ] || \   [ "$FORCE_INITIALIZE" = "true" ]then    CLONE_MODE="rsync all files to $DST_DISK root file system"    echo ""    if [ "$FORCE_INITIALIZE" = "true" ]    then        echo "Forcing a partition initialization of destination disk $DST_DISK"    else        echo "The destination disk $DST_DISK partition table does not"        echo "match the booted disk /dev/mmcblk0 partition table so a"        echo "destination disk initialize is required."    fi    echo "The existing destination disk '$DST_DISK' partitions are:"    parted /dev/$DST_DISK -s unit MB p 2>/dev/null \        | sed "/^Model/d ; /^Sector/d ; /^Disk Flags/d"#   if [ "$DST_BOOT_PARTITION_TYPE" != "$SRC_BOOT_PARTITION_TYPE" ]#   then#       echo -e "  ... Cannot find a destination boot file system of type: $SRC_BOOT_PARTITION_TYPE\n"#   fi#   if [ "$DST_ROOT_PARTITION_TYPE" != "$SRC_ROOT_PARTITION_TYPE" ]#   then#       echo -e "  ... Cannot find a destination root file system of type: $SRC_ROOT_PARTITION_TYPE\n"#   fi    echo "*** All data on destination disk $DST_DISK will be overwritten! ***"    echo ""    echo -n "Do you want to initialize the destination disk /dev/$DST_DISK? (yes/no): "    read resp    if [ "$resp" = "y" ] || [ "$resp" = "yes" ]    then        # Image onto the destination disk a beginning fragment of the        # running SD card file structure that spans at least more than        # the start of partition 2.        #        # Calculate the start of partition 2 in MB for the dd.        PART2_START=$(parted /dev/mmcblk0 -ms unit MB p | grep "^2" \                | cut -f 2 -d: | sed s/MB// | tr "," "." | cut -f 1 -d.)        # and add some slop        DD_COUNT=`expr $PART2_START + 8`        echo ""        echo "Imaging the partition structure, copying $DD_COUNT megabytes..."        sync        dd if=/dev/mmcblk0 of=/dev/$DST_DISK bs=1M count=$DD_COUNT        # Partition was copied live so fsck to clean up for possible future        # "Volume was not properly unmounted" warnings.        if [ "$HAVE_FSCK_VFAT" = "yes" ]        then            echo "Running fsck on $DST_BOOT_PARTITION..."            fsck -p $DST_BOOT_PARTITION &> /dev/null        fi        # But, though Partion 1 is now imaged, partition 2 is incomplete and        # maybe the wrong size for the destination SD card.  So fdisk it to        # make it fill the rest of the disk and mkfs it to clean it out.        #        echo "Sizing partition 2 (root partition) to use all SD card space..."        expand_rootfs        mkfs.ext4 -F $DST_ROOT_PARTITION        echo ""        echo "/dev/$DST_DISK is initialized and resized.  Its partitions are:"#       fdisk -l /dev/$DST_DISK | grep $DST_DISK        parted /dev/$DST_DISK unit MB p \            | sed "/^Model/d ; /^Sector/d ; /^Disk Flags/d"        SRC_ROOT_VOL_NAME=`e2label /dev/mmcblk0p2`        echo ""        echo "Your booted /dev/mmcblk0p2 rootfs existing label: $SRC_ROOT_VOL_NAME"        echo -n "You may enter a label for the destination rootfs $DST_ROOT_PARTITION: "        read resp        if [ "$resp" != "" ]        then            e2label $DST_ROOT_PARTITION $resp        fi    else        echo -e "Aborting\n"        exit 0    fifi# =========== Setup Summary ===========#DST_ROOT_VOL_NAME=`e2label $DST_ROOT_PARTITION`if [ "$DST_ROOT_VOL_NAME" = "" ]then    DST_ROOT_VOL_NAME="no label"fiecho ""echo "======== Clone Summary ========"echo "Clone mode               :  $CLONE_MODE"echo "Clone destination disk   :  $DST_DISK"echo "Clone destination rootfs :  $DST_ROOT_PARTITION ($DST_ROOT_VOL_NAME) on ${CLONE}"echo "Clone destination bootfs :  $DST_BOOT_PARTITION on ${CLONE}/boot"echo "Verbose mode             :  $VERBOSE"echo "==============================="# If this is an SD card initialization, can watch progress of the clone# in another terminal with:  watch df -h#echo -n "Final check, is it Ok to proceed with the clone (yes/no)?: "read respif [ "$resp" != "y" ] && [ "$resp" != "yes" ]then    echo -e "Aborting the disk clone.\n"    exit 0fi## =========== End of Setup  ===========# Mount destination filesystems.echo "=> Mounting $DST_ROOT_PARTITION ($DST_ROOT_VOL_NAME) on $CLONE"if ! mount $DST_ROOT_PARTITION $CLONEthen    echo -e "Mount failure of $DST_ROOT_PARTITION, aborting!\n"    exit 0fiif [ ! -d $CLONE/boot ]then    mkdir $CLONE/bootfiecho "=> Mounting $DST_BOOT_PARTITION on $CLONE/boot"if ! mount $DST_BOOT_PARTITION $CLONE/bootthen    umount $CLONE    echo -e "Mount failure of $DST_BOOT_PARTITION, aborting!\n"    exit 0fiecho "==============================="# Do not include a dhpys swapfile in the clone.  dhpys-swapfile will# regenerate it at boot.#if [ -f /etc/dphys-swapfile ]then    SWAPFILE=`cat /etc/dphys-swapfile | grep ^CONF_SWAPFILE | cut -f 2 -d=`    if [ "$SWAPFILE" = "" ]    then        SWAPFILE=/var/swap    fi    EXCLUDE_SWAPFILE="--exclude $SWAPFILE"fiSTART_TIME=`date '+%H:%M:%S'`# Exclude fuse mountpoint .gvfs, various other mount points, and tmpfs# file systems from the rsync.#syncecho "Starting the filesystem rsync to $DST_DISK"echo -n "(This may take several minutes)..."rsync $RSYNC_OPTIONS --delete \        $EXCLUDE_SWAPFILE \        --exclude '.gvfs' \        --exclude '/dev' \        --exclude '/media' \        --exclude '/mnt' \        --exclude '/proc' \        --exclude '/run' \        --exclude '/sys' \        --exclude '/tmp' \        --exclude 'lost\+found' \    // \    $CLONE# Fixup some stuff#for i in dev media mnt proc run sysdo    if [ ! -d $CLONE/$i ]    then        mkdir $CLONE/$i    fidoneif [ ! -d $CLONE/tmp ]then    mkdir $CLONE/tmp    chmod a+w $CLONE/tmpfi# Some extra optional dirs I create under /mntfor i in $OPTIONAL_MNT_DIRSdo    if [ ! -d $CLONE/mnt/$i ]    then        mkdir $CLONE/mnt/$i    fidonerm -f $CLONE/etc/udev/rules.d/70-persistent-net.rulesDATE=`date '+%F %H:%M'`echo "$DATE  $HOSTNAME $PGM : clone to $DST_DISK ($DST_ROOT_VOL_NAME)" \        >> $CLONE_LOGecho "$DATE  $HOSTNAME $PGM : clone to $DST_DISK ($DST_ROOT_VOL_NAME)" \        >> $CLONE/$CLONE_LOGSTOP_TIME=`date '+%H:%M:%S'`echo ""echo "*** Done with clone to /dev/$DST_DISK ***"echo "    Started: $START_TIME    Finished: $STOP_TIME"echo ""# Pause before unmounting in case I want to inspect the clone results# or need to custom modify any files on the destination SD clone.# Eg. modify $CLONE/etc/hostname, $CLONE/etc/network/interfaces, etc# if I'm cloning into a card to be installed on another Pi.#echo -n "Hit Enter when ready to unmount the /dev/$DST_DISK partitions..."read respecho "unmounting $CLONE/boot"umount $CLONE/bootecho "unmounting $CLONE"umount $CLONEecho "==============================="exit 0