Explorar el Código

add driver_can_socket.

yuchuli hace 3 años
padre
commit
c00925bfc4

+ 32 - 0
src/driver/driver_can_socket/basecan.cpp

@@ -0,0 +1,32 @@
+#include "basecan.h"
+
+basecan::basecan()
+{
+
+}
+
+basecan::~basecan()
+{
+    qDebug(" del basecan");
+}
+
+int basecan::GetMessage(const int nch,basecan_msg *pMsg, const int nCap)
+{
+    return 0;
+}
+
+int basecan::SetMessage(const int nch, basecan_msg *pMsg)
+{
+    return 0;
+}
+
+
+void basecan::startdev()
+{
+
+}
+
+void basecan::stopdev()
+{
+
+}

+ 38 - 0
src/driver/driver_can_socket/basecan.h

@@ -0,0 +1,38 @@
+#ifndef BASECAN_H
+#define BASECAN_H
+
+#include <QThread>
+
+#include "ivfault.h"
+#include "ivlog.h"
+
+class basecan_msg
+{
+  public:
+    unsigned int id;
+    bool isExtern;
+    bool isRemote;
+    unsigned char nLen;
+    unsigned char data[8];
+};
+
+class basecan : public QThread
+{
+    Q_OBJECT
+public:
+    basecan();
+    ~basecan();
+    virtual int GetMessage(const int nch,basecan_msg * pMsg,const int nCap);
+    virtual int SetMessage(const int nch,basecan_msg * pMsg); //Send Message
+
+    virtual void startdev();
+    virtual void stopdev();
+
+    iv::Ivfault *mfault = nullptr;
+    iv::Ivlog *mivlog = nullptr;
+signals:
+    void SIG_CANOPENSTATE(bool bCAN,int nR,const char * strres);
+    void SIGTEST();
+};
+
+#endif // BASECAN_H

+ 210 - 0
src/driver/driver_can_socket/canctrl.cpp

@@ -0,0 +1,210 @@
+#include "canctrl.h"
+
+#include <memory>
+
+canctrl * gc;
+static iv::canstate::canstate proCanSt;
+void Listencansend0(const char * strdata,const unsigned int nSize,const unsigned int index,const QDateTime * dt,const char * strmemname)
+{
+    iv::can::canmsg msg;
+
+    if(false == msg.ParseFromArray(strdata,nSize))
+    {
+        std::cout<<"Listencansend Parse fail."<<std::endl;
+        return;
+    }
+
+    gc->sendmsg(0,msg);
+
+}
+
+
+
+
+canctrl::canctrl(const char * strmemsend0,const char * strmemrecv0,const char * strcansend)
+{
+
+    gc = this;
+
+    mparecv0 = iv::modulecomm::RegisterSend(strmemrecv0,100000,3);
+    mpcanState = iv::modulecomm::RegisterSend("canstate",18,3);
+
+    mpasend0 = iv::modulecomm::RegisterRecv(strmemsend0,Listencansend0);
+
+    mpcan = new nvcan(strcansend);
+    mspcan.reset(mpcan);
+    connect(mpcan,SIGNAL(SIG_CANOPENSTATE(bool,int,const char*)),this,SLOT(onCANState(bool,int,const char*)));
+    mpcan->startdev();
+}
+
+canctrl::~canctrl()
+{
+    mpcan->stopdev();
+
+    delete mpcan;
+
+    iv::modulecomm::Unregister(mpasend0);
+    iv::modulecomm::Unregister(mpcanState);
+    iv::modulecomm::Unregister(mparecv0);
+
+}
+
+void canctrl::run()
+{
+
+    QTime xTime;
+    xTime.start();
+    int nOldTime = xTime.elapsed();
+    int i;
+
+
+    while(!isInterruptionRequested())
+    {
+        if(mbCANOpen)
+        {
+            basecan_msg xmsg[2500];
+            int nRec1,nRec2,nSend1,nSend2;
+            if((nRec1 =mpcan->GetMessage(0,xmsg,2500))>0)
+            {
+                sharecanmsg(mparecv0,xmsg,nRec1,0);
+            }
+
+
+
+            nSend1 = 0;
+            nSend2 = 0;
+
+            mMutexcan1.lock();
+            for(i=0;i<msendmsgvector1.size();i++)
+            {
+                mpcan->SetMessage(0,&(msendmsgvector1.at(i)));
+            }
+            msendmsgvector1.clear();
+            mMutexcan1.unlock();
+
+
+            proCanSt.set_b_canstate(true);
+            int nsize = proCanSt.ByteSize();
+            std::shared_ptr<char > strdata_ptr= std::shared_ptr<char>(new char[nsize]);
+            if(proCanSt.SerializeToArray(strdata_ptr.get(),nsize))
+            {
+                iv::modulecomm::ModuleSendMsg(mpcanState,strdata_ptr.get(),nsize);
+            }
+            msleep(1);
+        }
+        else
+        {
+            proCanSt.set_b_canstate(false);
+            int nsize = proCanSt.ByteSize();
+            char * strdata = new char[proCanSt.ByteSize()];
+            if(proCanSt.SerializeToArray(strdata,nsize))
+            {
+                iv::modulecomm::ModuleSendMsg(mpcanState,strdata,nsize);
+            }
+            delete strdata;
+            msleep(1);
+            mpcan->mivlog->error("%s open can card fail",__func__);
+
+            if(xTime.elapsed()>1000)
+            {
+                qDebug("Not Open CANCARD exceed 1 second. so exit program.");
+                exit(-1);
+            }
+        }
+//        mpcan->mfault->SetFaultState(0, 0, "ok");
+    }
+
+    qDebug("thread canctrl complete.");
+
+}
+
+void canctrl::onCANState(bool bCAN, int nR, const char *strres)
+{
+    mbCANOpen = bCAN;
+    mpcan->mivlog->info("can","canstate is %s ",strres);
+}
+
+void canctrl::sendmsg(int index, iv::can::canmsg xmsg)
+{
+
+    std::vector<basecan_msg> * psendmsgvector;
+    QMutex * pMutex;
+
+    pMutex = &mMutexcan1;
+    psendmsgvector = &msendmsgvector1;
+
+
+    if(psendmsgvector->size() > SENDMSGBUFSIZE)
+    {
+        mpcan->mivlog->warn("sendmsg buf full");
+        return;
+    }
+
+
+    pMutex->lock();
+    if(psendmsgvector->size() > 1000)psendmsgvector->clear();
+    int i;
+    for(i=0;i<xmsg.rawmsg_size();i++)
+    {
+        basecan_msg sendmsg;
+        iv::can::canraw x;
+        x.CopyFrom(xmsg.rawmsg(i));
+        sendmsg.id = x.id();
+        sendmsg.isExtern = x.bext();
+        sendmsg.isRemote = x.bremote();
+        int nlen = x.len();
+
+        if((nlen < 0) || (nlen > 8))
+        {
+            nlen = 0;
+            mpcan->mivlog->warn("sendmsg nlen err");
+            continue;
+ //           mpcan->mfault->SetFaultState(1, 0, "sendmsg nlen err");
+        }
+        sendmsg.nLen = nlen;
+        if(sendmsg.nLen > 0)
+        {
+            memcpy(sendmsg.data,x.data().data(),sendmsg.nLen);
+        }
+
+        psendmsgvector->push_back(sendmsg);
+    }
+    pMutex->unlock();
+
+
+}
+
+void canctrl::sharecanmsg(void *xpa, basecan_msg * pxmsg,int ncount,int nch)
+{
+    iv::can::canmsg xmsg;
+
+    int i;
+    for(i=0;i<ncount;i++)
+    {
+        iv::can::canraw * praw = xmsg.add_rawmsg();
+        praw->set_id(pxmsg[i].id);
+        praw->set_data(pxmsg[i].data,8);
+        praw->set_bext(pxmsg[i].isExtern);
+        praw->set_bremote(pxmsg[i].isRemote);
+        praw->set_rectime(QDateTime::currentMSecsSinceEpoch());
+        praw->set_len(pxmsg[i].nLen);
+
+    }
+    xmsg.set_channel(nch);
+
+    xmsg.set_index(mindex[nch]);
+    mindex[nch]++;
+
+    int nsize = xmsg.ByteSize();
+    char * strdata = new char[xmsg.ByteSize()];
+    if(xmsg.SerializePartialToArray(strdata,nsize))
+    {
+        iv::modulecomm::ModuleSendMsg(xpa,strdata,nsize);
+    }
+    else
+    {
+        mpcan->mivlog->warn("canctrl::sharecanmsg serialize error");
+//        mpcan->mfault->SetFaultState(1, 0, "sharecanmsg serialize error");
+    }
+    delete strdata;
+}

+ 50 - 0
src/driver/driver_can_socket/canctrl.h

@@ -0,0 +1,50 @@
+#ifndef CANCTRL_H
+#define CANCTRL_H
+
+#include <QThread>
+#include <QMutex>
+#include <memory>
+#include <QTimer>
+#include <array>
+#include <vector>
+#include <iostream>
+#include "nvcan.h"
+#include "modulecomm.h"
+#include "canmsg.pb.h"
+#include "canraw.pb.h"
+#include "canstate.pb.h"
+
+class canctrl : public QThread
+{
+    Q_OBJECT
+public:
+    canctrl(const char * strmemsend0,const char * strmemrecv0,const char * strcanname);
+    ~canctrl();
+
+private slots:
+    void onCANState(bool bCAN,int nR,const char * strres);
+
+private:
+    void run();
+
+    basecan * mpcan;
+    std::shared_ptr<basecan> mspcan;
+    bool mbCANOpen = false;
+
+    std::vector<basecan_msg> msendmsgvector1;
+    const int SENDMSGBUFSIZE = 3000;
+
+    QMutex mMutexcan1;
+
+    int mindex[2];
+
+    void * mpasend0,  * mparecv0,  *mpcanState;
+
+public:
+    void sendmsg(int index,iv::can::canmsg xmsg);
+    void sharecanmsg(void * xpa,basecan_msg * pxmsg,int ncount,int nch);
+
+
+};
+
+#endif // CANCTRL_H

+ 49 - 0
src/driver/driver_can_socket/driver_can_socket.pro

@@ -0,0 +1,49 @@
+QT -= gui
+
+QT += network xml dbus
+
+CONFIG += c++11 console
+CONFIG -= app_bundle
+
+QMAKE_LFLAGS += -no-pie
+
+DEFINES += NV
+
+# The following define makes your compiler emit warnings if you use
+# any feature of Qt which as been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+!include(../../../include/common.pri ) {
+    error( "Couldn't find the common.pri file!" )
+}
+
+!include(../../../include/ivprotobuf.pri ) {
+    error( "Couldn't find the ivprotobuf.pri file!" )
+}
+
+INCLUDEPATH += $$PWD/../../include/base/driver/can
+
+# You can also make your code fail to compile if you use deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += main.cpp \
+    nvcan.cpp \
+    canctrl.cpp \
+    ../../include/msgtype/canmsg.pb.cc \
+    ../../include/msgtype/canraw.pb.cc \
+    ../../include/msgtype/canstate.pb.cc \
+    ../../include/base/driver/can/basecan.cpp
+
+HEADERS += \
+    nvcan.h \
+    canctrl.h \
+    ../../include/msgtype/canmsg.pb.h \
+    ../../include/msgtype/canraw.pb.h \
+    ../../include/msgtype/canstate.pb.h \
+    ../../include/base/driver/can/basecan.h
+
+

+ 79 - 0
src/driver/driver_can_socket/main.cpp

@@ -0,0 +1,79 @@
+#include <QCoreApplication>
+#include <QObject>
+
+#include <signal.h>
+
+#include "nvcan.h"
+#include "canctrl.h"
+
+#include <unistd.h>
+
+#include <thread>
+#include <iostream>
+
+#include <xmlparam.h>
+
+#include "ivversion.h"
+#include "ivexit.h"
+#include <signal.h>
+
+
+static canctrl * gpcanctrl;
+
+void exitfunc()
+{
+    qDebug("enter exit func.");
+    gpcanctrl->requestInterruption();
+
+    QTime  xTime;
+    xTime.start();
+    while(xTime.elapsed()<1000)
+    {
+        if(gpcanctrl->isFinished())
+        {
+            qDebug("canctrl complete.");
+            delete gpcanctrl;
+            break;
+        }
+    }
+
+}
+
+void signal_handler(int sig)
+{
+    if(sig == SIGINT)
+    {
+        exitfunc();
+    }
+}
+
+
+int main(int argc, char *argv[])
+{
+    showversion("driver_can_nvidia_agx");
+    QCoreApplication a(argc, argv);
+
+
+    QString strpath = QCoreApplication::applicationDirPath();
+    if(argc < 2)
+        strpath = strpath + "/driver_can_socket.xml";
+    else
+        strpath = argv[1];
+    std::cout<<strpath.toStdString()<<std::endl;
+    iv::xmlparam::Xmlparam xp(strpath.toStdString());
+
+    std::string strmemsend0 = xp.GetParam("cansend0_agx","cansend0");
+    std::string strmemrecv0 = xp.GetParam("canrecv0_agx","canrecv0");
+    std::string strcanname = xp.GetParam("canname","can0");
+
+    gpcanctrl = new canctrl(strmemsend0.data(),strmemrecv0.data(),strcanname.data());
+    gpcanctrl->start();
+
+    iv::ivexit::RegIVExitCall(exitfunc);
+
+    signal(SIGINT,signal_handler);
+
+ //   std::thread b(func);
+
+    return a.exec();
+}

+ 350 - 0
src/driver/driver_can_socket/nvcan.cpp

@@ -0,0 +1,350 @@
+#include "nvcan.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <time.h>
+#include <errno.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <net/if.h>
+
+
+#include <linux/can.h>
+#include <linux/can/raw.h>
+
+#include <QDateTime>
+
+#include <iostream>
+
+/* for hardware timestamps - since Linux 2.6.30 */
+#ifndef SO_TIMESTAMPING
+#define SO_TIMESTAMPING 37
+#endif
+
+/* from #include <linux/net_tstamp.h> - since Linux 2.6.30 */
+#define SOF_TIMESTAMPING_SOFTWARE (1<<4)
+#define SOF_TIMESTAMPING_RX_SOFTWARE (1<<3)
+#define SOF_TIMESTAMPING_RAW_HARDWARE (1<<6)
+
+#define MAXSOCK 16    /* max. number of CAN interfaces given on the cmdline */
+#define MAXIFNAMES 30 /* size of receive name index to omit ioctls */
+#define MAXCOL 6      /* number of different colors for colorized output */
+#define ANYDEV "any"  /* name of interface to receive from any CAN interface */
+#define ANL "\r\n"    /* newline in ASC mode */
+
+#define SILENT_INI 42 /* detect user setting on commandline */
+#define SILENT_OFF 0  /* no silent mode */
+#define SILENT_ANI 1  /* silent mode with animation */
+#define SILENT_ON  2  /* silent mode (completely silent) */
+
+#include <QTime>
+
+#define BUF_SIZE 1000
+
+std::string CANNAME[] = {"can0","can1"};
+
+nvcan::nvcan(const char * strcanname)
+{
+//    qDebug("nvcan");
+//    connect(this,SIGNAL(SIG_CANOPENSTATE(bool,int,const char*)),this,SLOT(onMsg(bool,int,const char*)));
+
+    CANNAME[0] = strcanname;
+    mfault = new iv::Ivfault("can_socket");
+    mivlog = new iv::Ivlog("can_socket");
+
+
+    mfault->SetFaultState(0,0,"Prepare Initialize.");
+
+
+}
+
+void nvcan::run()
+{
+
+    int currmax = 1;
+    fd_set rdfs;
+    int s[MAXSOCK];
+    int ret;
+    
+    struct sockaddr_can addr;
+    char ctrlmsg[CMSG_SPACE(sizeof(struct timeval) + 3*sizeof(struct timespec) + sizeof(__u32))];
+    struct iovec iov;
+    struct msghdr msg;
+    struct canfd_frame frame;
+    int nbytes, i, maxdlen;
+    struct ifreq ifr;
+    struct timeval tv, last_tv;
+    struct timeval timeout_config = { 0, 0 }, *timeout_current = 0;
+
+    mfault->SetFaultState(0,0,"Initializing.");
+    
+    for(i=0;i<currmax;i++)
+    {
+        s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+        if (s[i] < 0) {
+            mfault->SetFaultState(2,1,"Create Socket Error.");
+            emit SIG_CANOPENSTATE(false,-1,"Create Socket Error");
+            return;
+        }
+
+        addr.can_family = AF_CAN;
+
+        memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
+        strncpy(ifr.ifr_name, CANNAME[i].data(), 5);
+
+        if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
+            mfault->SetFaultState(2,2,"SIOCGIFINDEX.");
+            emit SIG_CANOPENSTATE(false,-2,"SIOCGIFINDEX");
+            return;
+        }
+        addr.can_ifindex = ifr.ifr_ifindex;
+
+        if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+            mfault->SetFaultState(2,3,"bind error.");
+            emit SIG_CANOPENSTATE(false,-3,"bind error");
+            return;
+        }
+    }
+
+    mbCANOpen = true;
+    mivlog->verbose("open can succesfully.");
+    mfault->SetFaultState(0,0,"CAN OK.");
+    emit SIG_CANOPENSTATE(true,0,"open can card successfully");
+
+    iov.iov_base = &frame;
+    msg.msg_name = &addr;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = &ctrlmsg;
+
+    qint64 nLastRecv = QDateTime::currentMSecsSinceEpoch();
+    int nRecvState = 0; // 0 Have Data  1 No Data;
+
+    mbRunning = true;
+
+    int nrecvcount = 0;
+
+    while((!QThread::isInterruptionRequested())&&(mbCANOpen))
+    {
+        FD_ZERO(&rdfs);
+        for (i=0; i<currmax; i++)
+            FD_SET(s[i], &rdfs);
+
+        if (timeout_current)
+            *timeout_current = timeout_config;
+
+        timeout_config.tv_sec= 0;
+        timeout_config.tv_usec = 100;;
+        timeout_current = &timeout_config;
+        ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, timeout_current);
+        if (ret < 0) {
+            emit SIG_CANOPENSTATE(false,-4,"select error");
+            mfault->SetFaultState(2,4,"select error.");
+            mbCANOpen = false;
+            continue;
+        }
+
+        for (i=0; i<currmax; i++) {  /* check all CAN RAW sockets */
+
+            if (FD_ISSET(s[i], &rdfs)) {
+
+                nLastRecv = QDateTime::currentMSecsSinceEpoch();
+                /* these settings may be modified by recvmsg() */
+                iov.iov_len = sizeof(frame);
+                msg.msg_namelen = sizeof(addr);
+                msg.msg_controllen = sizeof(ctrlmsg);
+                msg.msg_flags = 0;
+
+                nbytes = recvmsg(s[i], &msg, 0);
+
+                if (nbytes < 0) {
+ //                   if ((errno == ENETDOWN) && !down_causes_exit) {
+                    if ((errno == ENETDOWN)) {
+                        mivlog->error("%s interface down", CANNAME[i].data());
+                        mfault->SetFaultState(1, 0, "interface down");
+                        emit SIG_CANOPENSTATE(false,-5,"can card down");
+                        fprintf(stderr, "%s: interface down\n", CANNAME[i].data());
+                        return;
+                    }
+                    continue;
+//                    perror("read");
+//                    return 1;
+                }
+
+                if ((size_t)nbytes == CAN_MTU)
+                    maxdlen = CAN_MAX_DLEN;
+                else if ((size_t)nbytes == CANFD_MTU)
+                    maxdlen = CANFD_MAX_DLEN;
+                else {
+                    mivlog->warn("read incomplete message");
+                    continue;
+                }
+
+                nrecvcount++;
+  //              qDebug("receive msg.");
+                mMutex.lock();
+
+                basecan_msg msg;
+                msg.id = frame.can_id&0x1fffffff;
+                if((frame.can_id&0x80000000)!= 0)msg.isExtern = true;
+                else msg.isExtern = false;
+                if((frame.can_id&0x40000000)!= 0)msg.isRemote = true;
+                else msg.isRemote = false;
+                msg.nLen = frame.len;
+                if((frame.len<9)&&(frame.len>0))memcpy(msg.data,frame.data,frame.len);
+                if(mMsgRecvBuf[i].size()<BUF_SIZE)
+                {
+                    mMsgRecvBuf[i].push_back(msg);
+                }
+
+                mMutex.unlock();
+
+            }
+        }
+
+        if((QDateTime::currentMSecsSinceEpoch() - nLastRecv)> 1000)
+        {
+            if(nRecvState == 0)
+            {
+                nRecvState = -1;
+                mfault->SetFaultState(0,1,"More than 1 second not receive data.");
+            }
+        }
+        else
+        {
+            if(nRecvState == -1)
+            {
+                nRecvState = 0;
+                mfault->SetFaultState(0,0,"CAN OK.");
+            }
+        }
+
+        struct canfd_frame framesend[2500];
+
+        for(int nch =0;nch<currmax;nch++)
+        {
+            int nsend = 0;
+            mMutex.lock();
+            for(i=0;i<mMsgSendBuf[nch].size();i++)
+            {
+                if(i>=2500)break;
+                memcpy(framesend[i].data,mMsgSendBuf[nch].at(i).data,8);
+                framesend[i].can_id = mMsgSendBuf[nch].at(i).id;
+                if(mMsgSendBuf[nch].at(i).isExtern)
+                {
+                    framesend[i].can_id = framesend[i].can_id|0x80000000;
+                }
+                else
+                {
+                    framesend[i].can_id = framesend[i].can_id&0x7ff;
+                }
+                if(mMsgSendBuf[nch].at(i).isRemote)
+                {
+                    framesend[i].can_id= framesend[i].can_id|0x40000000;
+                }
+
+                framesend[i].len = mMsgSendBuf[nch].at(i).nLen;
+
+                nsend++;
+            }
+            mMsgSendBuf[nch].clear();
+            mMutex.unlock();
+            if(nsend > 0)
+            {
+                for(i=0;i<nsend;i++)
+                if (write(s[nch], &framesend[i],16) != 16) {
+                    mivlog->error("write error 1");
+                    perror("write error 1.");
+                    continue;
+                }
+            }
+
+        }
+
+    }
+
+    for (i=0; i<currmax; i++)
+    {
+        close(s[i]);
+    }
+    qDebug("nvcan thread close.");
+    mbRunning = false;
+}
+
+void nvcan::startdev()
+{
+    start();
+}
+
+void nvcan::stopdev()
+{
+    requestInterruption();
+    QTime xTime;
+    xTime.start();
+    while(xTime.elapsed()<100)
+    {
+        if(mbRunning == false)
+        {
+            mfault->SetFaultState(1, 0, "can closed");
+            mivlog->error("can is closed at %d",xTime.elapsed());
+            qDebug("can is closed.");
+            break;
+        }
+    }
+}
+
+int nvcan::GetMessage(const int nch,basecan_msg *pMsg, const int nCap)
+{
+    if((nch>1)||(nch < 0))return -1;
+    if(mMsgRecvBuf[nch].size() == 0)return 0;
+
+    int nRtn;
+    nRtn = nCap;
+    mMutex.lock();
+    if(nRtn > mMsgRecvBuf[nch].size())nRtn = mMsgRecvBuf[nch].size();
+    int i;
+    for(i=0;i<nRtn;i++)
+    {
+        memcpy(&pMsg[i],&(mMsgRecvBuf[nch].at(i)),sizeof(basecan_msg));
+    }
+
+    std::vector<basecan_msg>::iterator iter;
+    iter = mMsgRecvBuf[nch].begin();
+    for(i=0;i<nRtn;i++)
+    {
+        iter = mMsgRecvBuf[nch].erase(iter);
+    }
+
+    mMutex.unlock();
+
+    return nRtn;
+
+}
+
+int nvcan::SetMessage(const int nch, basecan_msg *pMsg)
+{
+    if((nch>1)||(nch < 0))return -1;
+
+    if(mMsgSendBuf[nch].size() > BUF_SIZE)return -2;
+
+    mMutex.lock();
+    mMsgSendBuf[nch].push_back(*pMsg);
+    mMutex.unlock();
+    return 0;
+}
+
+void nvcan::onMsg(bool bCAN, int nR, const char *strres)
+{
+    mivlog->verbose("msg is %s ",strres);
+}
+

+ 38 - 0
src/driver/driver_can_socket/nvcan.h

@@ -0,0 +1,38 @@
+#ifndef NVCAN_H
+#define NVCAN_H
+#include "basecan.h"
+
+#include <vector>
+#include <QMutex>
+
+#include <thread>
+
+class nvcan : public basecan
+{
+    Q_OBJECT
+public:
+    nvcan(const char * strcanname);
+public:
+    void startdev();
+    void stopdev();
+
+    int GetMessage(const int nch,basecan_msg * pMsg,const int nCap);
+    int SetMessage(const int nch,basecan_msg * pMsg);
+
+private slots:
+    void onMsg(bool bCAN,int nR,const char * strres);
+
+private:
+    void run();
+    std::vector<basecan_msg> mMsgRecvBuf[2];
+
+    std::vector<basecan_msg> mMsgSendBuf[2];
+
+    QMutex mMutex;
+
+    bool mbCANOpen = false;
+    bool mbRunning = false;
+    int mnDevNum;
+};
+
+#endif // NVCAN_H

+ 16 - 1
src/tool/picview_civetweb/frontend/indexpic.html

@@ -16,20 +16,29 @@ var xc=0
 var int2=self.setInterval('changeImage()',29);
 
 	var n = 0;
+	var ic = 0;
 	var image=new Image();//放入函数里面:浏览器运行一分钟左右系统内存用到高达90%,故做一个全局的反冲图片
 	function changeImage()
 	{ 
+		if(ic == 1)
+		{
+			return;
+		}
+		ic = 1;
 		var canvas=document.getElementById("myCanvas2");  
 		var cxt=canvas.getContext("2d");
 		//ctx.restore();
 		image.src="./pic?"+n;
 		n++; 
 		var nerror = 0;
+		
 		image.onload = function () //确保图片已经加载完毕  
 		{  
 			if (image.complete)//如果图片加载完成,绘制
 			{
+				cxt.save();
 				cxt.drawImage(image,0,0);  
+				cxt.restore();
 				nerror = 0;
 			}
 			else
@@ -41,17 +50,23 @@ var int2=self.setInterval('changeImage()',29);
 					nerror = 0;
 				}
 			}
+			ic = 0;
 			
 		}  
 		image.onerror=function(){  
 			document.getElementById("F2").innerHTML="error N:"+n; 
+			ic = 0;
 		};  
 		//ctx.save();
   	}
 
 function clock() 
 { 
-	changeImage();
+	if(ic == 0)
+	{
+		ic = 1;
+		changeImage();
+	}
 } 
 function load() {
 	changeImage();

+ 2 - 1
src/tool/picview_civetweb/main.cpp

@@ -150,13 +150,14 @@ int main(int argc, char *argv[])
 
     iv::xmlparam::Xmlparam xp("./picview_civetweb.xml");
     std::string strmsgname =  xp.GetParam("imagemsgname","picfront");
+    std::string strport = xp.GetParam("Port","6123");
     gpa = iv::modulecomm::RegisterRecv(strmsgname.data(),Listenpic);
 
     mg_init_library(0);
 
 
     const char *options[] = {
-        "document_root", DOCUMENT_ROOT, "listening_ports", PORT, 0};
+        "document_root", DOCUMENT_ROOT, "listening_ports", strport.data(), 0};
 
     std::vector<std::string> cpp_options;
     for (int i=0; i<(sizeof(options)/sizeof(options[0])-1); i++) {