Отправка файла из приложения Android на Raspberry Pi с использованием SSH - PullRequest
0 голосов
/ 07 июня 2019

Я пытаюсь отправить файл из приложения для Android в RaspberryPi через WIFI.

Я могу подключиться к RPI и отправить ему команды через SSH.

это функция, которую я использую для отправки команды ssh:

public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
            throws Exception {

        JSch jsch = new JSch();
        Session session = jsch.getSession(username, hostname, port);
        session.setPassword(password);

        // Avoid asking for key confirmation
        Properties prop = new Properties();
        prop.put("StrictHostKeyChecking", "no");
        session.setConfig(prop);

        session.connect();

        // SSH Channel
        ChannelExec channelssh = (ChannelExec)
                session.openChannel("exec");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        channelssh.setOutputStream(baos);

        // Execute command

        channelssh.setCommand("scp " + file + " " + username + "@" + hostname + ":/home/pi/Desktop");
        channelssh.connect();
        try{Thread.sleep(5000);}catch(Exception ee){}
        channelssh.disconnect();
        return baos.toString();
    }

и это команда SSH, которая будет отправлена ​​

scp /storage/emulated/0/Download/201906071017.txt pi@192.168.4.1:/home/pi/Desktop

Я попытался запустить команду SSH на терминале Windows, и он успешно загрузил файл

Edit:

Я добавил этот код между .connect() и .disconnect(), чтобы дождаться ответа от команды на отключение от RPi

        channelssh.setErrStream(System.err);

        InputStream in=channelssh.getInputStream();

        channelssh.connect();

        byte[] tmp=new byte[1024];
        while(true){
            while(in.available()>0){
                int i=in.read(tmp, 0, 1024);
                if(i<0)break;
                System.out.print(new String(tmp, 0, i));
            }
            if(channelssh.isClosed()){
                if(in.available()>0) continue;
                System.out.println("exit-status: "+channelssh.getExitStatus());
                break;
            }
            try{Thread.sleep(1000);}catch(Exception ee){}
        }

        channelssh.disconnect();

Теперь я получаю отказ в разрешении в логах, имя пользователя и пароль верны.

W/System.err: Permission denied, please try again.
W/System.err: Permission denied, please try again.
W/System.err: Permission denied (publickey,password).
W/System.err: lost connection
I/System.out: exit-status: 1

1 Ответ

1 голос
/ 10 июня 2019

Я сделал это !! В итоге я загрузил файл с помощью службы sftp я использовал ChannelSsh с ChannelExec. Я должен был использовать ChannelSftp

Вот рабочий код

package com.example.a.sitetool;

import android.util.Log;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class RpiUpdate {


    public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
            throws Exception {

        Log.d("MainActivity", "Entered executeRemoteCommand");

        JSch jsch = new JSch();
        Session session = jsch.getSession(username, hostname, port);
        session.setPassword(password);

        // Avoid asking for key confirmation
        Properties prop = new Properties();
        prop.put("StrictHostKeyChecking", "no");
        session.setConfig(prop);

        session.connect();

        // SSH Channel
        Channel channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp channelsftp = (ChannelSftp) channel;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        channelsftp.cd("/home/pi/Desktop");
        channelsftp.put(new FileInputStream(file), file.getName());
        channelsftp.setOutputStream(baos);

        // Execute command
        channelsftp.put(file.getName(),"/home/pi/Desktop");

        InputStream in=channelsftp.getInputStream();

        byte[] tmp=new byte[1024];
        while(true){
            while(in.available()>0){
                int i=in.read(tmp, 0, 1024);
                if(i<0)break;
                System.out.print(new String(tmp, 0, i));
            }
            if(channelsftp.isClosed()){
                if(in.available()>0) continue;
                System.out.println("exit-status: "+channelsftp.getExitStatus());
                break;
            }
            try{Thread.sleep(1000);}catch(Exception ee){}
        }

        channel.disconnect();

        return baos.toString();
    }
}

Edit: Я оптимизировал код и удалил ByteArrayOutputStream, так как он не нужен для Channelsftp. Это изменение привело к возврату void вместо String Я также добавил возможность изменять разрешение для выходного файла.

package com.example.a.sitetool;

import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;

public class RpiUpdate {
    private static boolean success;


    public static void update() {
        //TODO add online version checking and download
        if (success)
            uploadFile();

    }

    private static void uploadFile() {
        Log.d("RPIUpdate", "Entered upload File");
        success=false;
        new AsyncTask<Integer, Void, Void>() {
            @Override
            protected Void doInBackground(Integer... params) {
                try {
                    executeRemoteCommand("pi", "rbs", "192.168.4.1", 22);
                    Log.d("MainActivity", "File Uploaded");
                    success = true;
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d("MainActivity", "Failed to upload file");
                    success = false;
                }
                return null;
            }
        }.execute(1);
    }


public static void executeRemoteCommand(final String username, final String password, final String hostname, final int port)
            throws Exception {
        Log.d("RPiUpdate", "Entered executeRemoteCommand");

        //Creating the path on android to bbserver.py
        File root;
        root = new File(Environment.getExternalStorageDirectory() + File.separator + "Download");
        if (!root.exists()) {
            root.mkdirs();
        }
        File file = new File(root, "bbserver.py");

        JSch jsch = new JSch();
        Session session = jsch.getSession(username, hostname, port);
        session.setPassword(password);

        // Avoid asking for key confirmation
        Properties prop = new Properties();
        prop.put("StrictHostKeyChecking", "no");
        session.setConfig(prop);

        session.connect();

        //SFTP setup
        Channel channel = session.openChannel("sftp");
        channel.connect();

        ChannelSftp channelsftp = (ChannelSftp) channel;
        //Renaming the old bbserver.py
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd:HH:mm", Locale.ENGLISH);
        Date now = new Date();
        channelsftp.cd("/home/pi/Desktop");
        // 384 in octal is 600. This makes the file non executable. only readable and writable

        channelsftp.chmod(384, "/home/pi/Desktop/bbserver.py");

        channelsftp.rename("/home/pi/Desktop/bbserver.py", "/home/pi/Desktop/bbserver" + formatter.format(now) + ".py");

        //sending the new bbserver.py file
        channelsftp.put(new FileInputStream(file), file.getName());
        Log.d("RPiUpdate", "Sent file");

        //511 in octal is 777. This gives the file all available permissions(read, write, execute). thus making the file an executable

        channelsftp.chmod(511, "/home/pi/Desktop/" + file.getName());
        Log.d("RPiUpdate", "Changed permissions");

        channel.disconnect();

    }

...