<commit_before>// Copyright (c) 2009-2016 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Developers
// Copyright (c) 2015-2016 Silk Network
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "protocol.h"
#include "util.h"

#ifndef WIN32
# include <arpa/inet.h>
#endif

static const char* ppszTypeName[] =
{
    "ERROR",
    "tx",
    "block",
    "filtered block",
    "tx lock request",
    "tx lock vote",
    "spork",
    "sn winner",
    "sn scan error",
    "sn budget vote",
    "sn budget proposal",
    "sn budget finalized",
    "sn budget finalized vote",
    "sn quorum",
    "sn announce",
    "sn ping",
    "sstx"
};

CMessageHeader::CMessageHeader()
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    pchCommand[1] = 1;
    nMessageSize = -1;
    nChecksum = 0;
}

CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    strncpy(pchCommand, pszCommand, COMMAND_SIZE);
    nMessageSize = nMessageSizeIn;
    nChecksum = 0;
}

std::string CMessageHeader::GetCommand() const
{
        return std::string(pchCommand, pchCommand + COMMAND_SIZE);
}

bool CMessageHeader::IsValid() const
{
    // Check start string
    if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0)
        return false;

    // Check the command string for errors
    for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
    {
        if (*p1 == 0)
        {
            // Must be all zeros after the first zero
            for (; p1 < pchCommand + COMMAND_SIZE; p1++)
                if (*p1 != 0)
                    return false;
        }
        else if (*p1 < ' ' || *p1 > 0x7E)
            return false;
    }

    // Message size
    if (nMessageSize > MAX_SIZE)
    {
        LogPrintf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
        return false;
    }

    return true;
}

CAddress::CAddress() : CService()
{
    Init();
}

CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn)
{
    Init();
    nServices = nServicesIn;
}

void CAddress::Init()
{
    nServices = NODE_NETWORK;
    nTime = 100000000;
    nLastTry = 0;
}

CInv::CInv()
{
    type = 0;
    hash = 0;
}

CInv::CInv(int typeIn, const uint256& hashIn)
{
    type = typeIn;
    hash = hashIn;
}

CInv::CInv(const std::string& strType, const uint256& hashIn)
{
    unsigned int i;
    for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
    {
        if (strType == ppszTypeName[i])
        {
            type = i;
            break;
        }
    }
    if (i == ARRAYLEN(ppszTypeName))
        LogPrint("net", "CInv::CInv(string, uint256) : unknown type '%s'", strType);
    hash = hashIn;
}

bool operator<(const CInv& a, const CInv& b)
{
    return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}

bool CInv::IsKnownType() const
{
    return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
}

const char* CInv::GetCommand() const
{
    if (!IsKnownType())
        LogPrint("net", "CInv::GetCommand() : type=%d unknown type", type);
    return ppszTypeName[type];
}

std::string CInv::ToString() const
{
    return strprintf("%s %s", GetCommand(), hash.ToString());
}

void CInv::print() const
{
    LogPrintf("CInv(%s)\n", ToString());
}
<commit_msg>Update protocol.cpp<commit_after>// Copyright (c) 2009-2016 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Developers
// Copyright (c) 2015-2016 Silk Network
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "protocol.h"
#include "util.h"

#ifndef WIN32
# include <arpa/inet.h>
#endif

static const char* ppszTypeName[] =
{
    "ERROR",
    "tx",
    "block",
    "filtered block",
    "tx lock request",
    "tx lock vote",
    "spork",
    "sn winner",
    "sn scan error",
    "sn budget vote",
    "sn budget proposal",
    "sn budget finalized",
    "sn budget finalized vote",
    "sn quorum",
    "sn announce",
    "sn ping",
    "sstx"
};

CMessageHeader::CMessageHeader()
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    pchCommand[1] = 1;
    nMessageSize = -1;
    nChecksum = 0;
}

CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
    memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
    memset(pchCommand, 0, sizeof(pchCommand));
    strncpy(pchCommand, pszCommand, COMMAND_SIZE);
    nMessageSize = nMessageSizeIn;
    nChecksum = 0;
}

std::string CMessageHeader::GetCommand() const
{
    if (pchCommand[COMMAND_SIZE-1] == 0)
        return std::string(pchCommand, pchCommand + strlen(pchCommand));
    else
        return std::string(pchCommand, pchCommand + COMMAND_SIZE);
}

bool CMessageHeader::IsValid() const
{
    // Check start string
    if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0)
        return false;

    // Check the command string for errors
    for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
    {
        if (*p1 == 0)
        {
            // Must be all zeros after the first zero
            for (; p1 < pchCommand + COMMAND_SIZE; p1++)
                if (*p1 != 0)
                    return false;
        }
        else if (*p1 < ' ' || *p1 > 0x7E)
            return false;
    }

    // Message size
    if (nMessageSize > MAX_SIZE)
    {
        LogPrintf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
        return false;
    }

    return true;
}

CAddress::CAddress() : CService()
{
    Init();
}

CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn)
{
    Init();
    nServices = nServicesIn;
}

void CAddress::Init()
{
    nServices = NODE_NETWORK;
    nTime = 100000000;
    nLastTry = 0;
}

CInv::CInv()
{
    type = 0;
    hash = 0;
}

CInv::CInv(int typeIn, const uint256& hashIn)
{
    type = typeIn;
    hash = hashIn;
}

CInv::CInv(const std::string& strType, const uint256& hashIn)
{
    unsigned int i;
    for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
    {
        if (strType == ppszTypeName[i])
        {
            type = i;
            break;
        }
    }
    if (i == ARRAYLEN(ppszTypeName))
        LogPrint("net", "CInv::CInv(string, uint256) : unknown type '%s'", strType);
    hash = hashIn;
}

bool operator<(const CInv& a, const CInv& b)
{
    return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}

bool CInv::IsKnownType() const
{
    return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
}

const char* CInv::GetCommand() const
{
    if (!IsKnownType())
        LogPrint("net", "CInv::GetCommand() : type=%d unknown type", type);
    return ppszTypeName[type];
}

std::string CInv::ToString() const
{
    return strprintf("%s %s", GetCommand(), hash.ToString());
}

void CInv::print() const
{
    LogPrintf("CInv(%s)\n", ToString());
}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright © 2017-2018 Ruben Van Boxem
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 **/

#include "gui/events/xcb.h++"

#include "gui/native_window/xcb.h++"
#include "gui/window.h++"

#include <core/debug.h++>

namespace
{
  std::uint8_t mask_send_event_bit(std::uint8_t response_type)
  {
    return response_type & 0b0111'1111;
  }
}

namespace skui
{
  namespace gui
  {
    namespace events
    {
      xcb::xcb(gui::window& window)
        : base{window}
      {
        auto native_xcb_window = dynamic_cast<native_window::xcb*>(&window.get_native_window());
        if(!native_xcb_window)
          core::debug_print("events::xcb requires a native_window::xcb or native_window::xlib.\n");

        connection = native_xcb_window->get_connection();
        xcb_window = native_xcb_window->get_window();

        // The magic incantation to receive and be able to check for the "window was closed" event
        xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, true, 12, "WM_PROTOCOLS");
        core::unique_free_ptr<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(connection, cookie, nullptr));

        xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(connection, false, 16, "WM_DELETE_WINDOW");
        wm_delete_window.reset(xcb_intern_atom_reply(connection, cookie2, nullptr));

        xcb_change_property(connection,
                            XCB_PROP_MODE_REPLACE,
                            xcb_window,
                            reply->atom, 4, 32, 1, &wm_delete_window->atom);
        // end magic

        xcb_flush(connection);
      }

      xcb::~xcb() = default;

      void xcb::exec()
      {
        bool running = true;

        while(running)
        {
          core::unique_free_ptr<xcb_generic_event_t> event_ptr(xcb_wait_for_event(connection));
          if(!event_ptr)
          {
            core::debug_print("Call to xcb_wait_for_event failed. Most likely an I/O error.\n");
            running = false;
            break;
          }

          switch(mask_send_event_bit(event_ptr->response_type))
          {
            case XCB_EXPOSE:
            {
              const auto& expose = reinterpret_cast<const xcb_expose_event_t&>(*event_ptr);
              if(expose.count>0)
                continue;

              window.repaint();

              break;
            }
            case XCB_UNMAP_NOTIFY:
            {
              //const auto& unmap = reinterpret_cast<const xcb_unmap_notify_event_t&>(*event_ptr);
              break;
            }
            case XCB_BUTTON_PRESS:
            {
              auto button_press = reinterpret_cast<xcb_button_press_event_t*>(event_ptr.get());

              switch (button_press->state)
              {
                case XCB_BUTTON_MASK_1:
                  core::debug_print("Primary mouse button pressed.");
                  break;
              }

              switch (button_press->detail)
              {
                case 4:
                  // Wheel button up
                  break;
                case 5:
                  // wheel button down
                  break;
                default:
                  core::debug_print("Button ", button_press->detail, " pressed in window ", button_press->event, ", at coordinates (", button_press->event_x, ",", button_press->event, ").\n");
                  break;
              }
              break;
            }
            case XCB_BUTTON_RELEASE:
            {
              //auto button_release = reinterpret_cast<xcb_button_release_event_t*>(event_ptr.get());
              //implementation::print_modifiers(button_release->state);
              break;
            }
            case XCB_MOTION_NOTIFY:
            {
              //auto motion = reinterpret_cast<xcb_motion_notify_event_t*>(event_ptr.get());
              break;
            }
            case XCB_ENTER_NOTIFY:
            {
              //auto enter = reinterpret_cast<xcb_enter_notify_event_t*>(event_ptr.get());
              break;
            }
            case XCB_LEAVE_NOTIFY:
            {
              //auto leave = reinterpret_cast<xcb_leave_notify_event_t*>(event_ptr.get());
              break;
            }
            case XCB_KEY_PRESS:
            {
              //const auto& key_press = reinterpret_cast<xcb_key_press_event_t&>(*event_ptr);
              //implementation::print_modifiers(key_press->state);
              break;
            }
            case XCB_KEY_RELEASE:
            {
              //const auto& key_release = reinterpret_cast<xcb_key_release_event_t*>(*event_ptr);
              //implementation::print_modifiers(key_release->state);
              break;
            }
            case XCB_CONFIGURE_NOTIFY:
            {
              // We send out an event here so when maximizing or minimizing a window, it gets repainted properly
              const auto& configure_notify = *reinterpret_cast<xcb_configure_notify_event_t*>(event_ptr.get());
              // xcb_send_event is hardcoded to read 32 bytes regardless the event type, so give it 32 bytes.
              core::unique_free_ptr<xcb_expose_event_t> event(reinterpret_cast<xcb_expose_event_t*>(std::calloc(1, 32)));
              event->response_type = XCB_EXPOSE;
              event->window = xcb_window;
              event->x = static_cast<std::uint16_t>(configure_notify.x);
              event->y = static_cast<std::uint16_t>(configure_notify.y);
              event->width = configure_notify.width;
              event->height = configure_notify.height;

              xcb_send_event(connection, false, xcb_window, XCB_EVENT_MASK_EXPOSURE, reinterpret_cast<char*>(event.get()));
              xcb_flush(connection);

              break;
            }
            case XCB_CLIENT_MESSAGE:
            {
              const auto& client_message = reinterpret_cast<const xcb_client_message_event_t&>(*event_ptr);

              if(client_message.data.data32[0] == wm_delete_window->atom)
              {
                core::debug_print("WM_DELETE_WINDOW received.\n");
                window.close();
              }
              break;
            }
            case XCB_DESTROY_NOTIFY:
            {
              running = false;
              break;
            }
            default:
              core::debug_print("Unknown event: ", (int)mask_send_event_bit(event_ptr->response_type), ".\n");
              break;
          }
        }
      }
    }
  }
}
<commit_msg>Don't send an expose event on configure, this triggers too many repaints. Instead, force a repaint on a MapEvent.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright © 2017-2018 Ruben Van Boxem
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 **/

#include "gui/events/xcb.h++"

#include "gui/native_window/xcb.h++"
#include "gui/window.h++"

#include <core/debug.h++>

namespace
{
  std::uint8_t mask_send_event_bit(std::uint8_t response_type)
  {
    return response_type & 0b0111'1111;
  }
}

namespace skui
{
  namespace gui
  {
    namespace events
    {
      xcb::xcb(gui::window& window)
        : base{window}
      {
        auto native_xcb_window = dynamic_cast<native_window::xcb*>(&window.get_native_window());
        if(!native_xcb_window)
          core::debug_print("events::xcb requires a native_window::xcb or native_window::xlib.\n");

        connection = native_xcb_window->get_connection();
        xcb_window = native_xcb_window->get_window();

        // The magic incantation to receive and be able to check for the "window was closed" event
        xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, true, 12, "WM_PROTOCOLS");
        core::unique_free_ptr<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(connection, cookie, nullptr));

        xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(connection, false, 16, "WM_DELETE_WINDOW");
        wm_delete_window.reset(xcb_intern_atom_reply(connection, cookie2, nullptr));

        xcb_change_property(connection,
                            XCB_PROP_MODE_REPLACE,
                            xcb_window,
                            reply->atom, 4, 32, 1, &wm_delete_window->atom);
        // end magic

        xcb_flush(connection);
      }

      xcb::~xcb() = default;

      void xcb::exec()
      {
        bool running = true;

        while(running)
        {
          core::unique_free_ptr<xcb_generic_event_t> event_ptr(xcb_wait_for_event(connection));
          if(!event_ptr)
          {
            core::debug_print("Call to xcb_wait_for_event failed. Most likely an I/O error.\n");
            running = false;
            break;
          }

          switch(mask_send_event_bit(event_ptr->response_type))
          {
            case XCB_EXPOSE:
            {
              const auto& expose = reinterpret_cast<const xcb_expose_event_t&>(*event_ptr);
              if(expose.count>0)
                continue;

              window.repaint();

              break;
            }
            case XCB_UNMAP_NOTIFY:
            {
              //const auto& unmap = reinterpret_cast<const xcb_unmap_notify_event_t&>(*event_ptr);
              break;
            }
            case XCB_MAP_NOTIFY:
            {
              //const auto& map = reinterpret_cast<const xcb_map_notify_event_t&>(*event_ptr);
              window.state = window_state::windowed;

              // Force a repaint on map. This ensures a unminized window is properly displayed.
              window.repaint(true);

              break;
            }
            case XCB_BUTTON_PRESS:
            {
              auto button_press = reinterpret_cast<xcb_button_press_event_t*>(event_ptr.get());

              switch (button_press->state)
              {
                case XCB_BUTTON_MASK_1:
                  core::debug_print("Primary mouse button pressed.");
                  break;
              }

              switch (button_press->detail)
              {
                case 4:
                  // Wheel button up
                  break;
                case 5:
                  // wheel button down
                  break;
                default:
                  core::debug_print("Button ", button_press->detail, " pressed in window ", button_press->event, ", at coordinates (", button_press->event_x, ",", button_press->event, ").\n");
                  break;
              }
              break;
            }
            case XCB_BUTTON_RELEASE:
            {
              //auto button_release = reinterpret_cast<xcb_button_release_event_t*>(event_ptr.get());
              //implementation::print_modifiers(button_release->state);
              break;
            }
            case XCB_MOTION_NOTIFY:
            {
              //auto motion = reinterpret_cast<xcb_motion_notify_event_t*>(event_ptr.get());
              break;
            }
            case XCB_ENTER_NOTIFY:
            {
              //auto enter = reinterpret_cast<xcb_enter_notify_event_t*>(event_ptr.get());
              break;
            }
            case XCB_LEAVE_NOTIFY:
            {
              //auto leave = reinterpret_cast<xcb_leave_notify_event_t*>(event_ptr.get());
              break;
            }
            case XCB_KEY_PRESS:
            {
              //const auto& key_press = reinterpret_cast<xcb_key_press_event_t&>(*event_ptr);
              //implementation::print_modifiers(key_press->state);
              break;
            }
            case XCB_KEY_RELEASE:
            {
              //const auto& key_release = reinterpret_cast<xcb_key_release_event_t*>(*event_ptr);
              //implementation::print_modifiers(key_release->state);
              break;
            }
            case XCB_CONFIGURE_NOTIFY:
            {
              //const auto& configure_notify = reinterpret_cast<const xcb_configure_notify_event_t&>(*event_ptr);
              break;
            }
            case XCB_CLIENT_MESSAGE:
            {
              const auto& client_message = reinterpret_cast<const xcb_client_message_event_t&>(*event_ptr);

              if(client_message.data.data32[0] == wm_delete_window->atom)
              {
                core::debug_print("WM_DELETE_WINDOW received.\n");
                window.close();
              }
              break;
            }
            case XCB_DESTROY_NOTIFY:
            {
              running = false;
              break;
            }
            default:
              core::debug_print("Unknown event: ", (int)mask_send_event_bit(event_ptr->response_type), ".\n");
              break;
          }
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>
#include "SerialPort.h"
#include <ios>
#include <locale>

#include "Logging.h"
#undef   LOG_CLASS
#define  LOG_CLASS "SerialPort"

SerialPort::SerialPort(int portNumber) :
	m_iPortNumber(portNumber),
	m_hPort(0)
{
	// build short name from port number
	std::stringstream strPortName;
	strPortName << "COM" << m_iPortNumber;
	m_strPortName = strPortName.str();

	// build filename from port number
	std::stringstream strFileName;
	strFileName << "\\\\.\\COM" << m_iPortNumber;
	m_strFileName = strFileName.str();
}

bool SerialPort::exists() const
{
	// source: http://stackoverflow.com/questions/1205383/listing-serial-com-ports-on-windows

	std::wstring strPortNameW(m_strPortName.begin(), m_strPortName.end()); // convert to wchar
	COMMCONFIG config;
	DWORD      configSize = sizeof(config);
	// Port exists if configuration can be retrieved (returns true)
	// or the config structure size changes to indicate it was too small.
	return (GetDefaultCommConfigW(strPortNameW.c_str(), &config, &configSize) == TRUE) ||
	       (configSize != sizeof(config));
}

bool SerialPort::open()
{
	if (!isOpen())
	{
		std::wstring strFileNameW(m_strFileName.begin(), m_strFileName.end()); // convert to wchar
		m_hPort = ::CreateFile(
			strFileNameW.c_str(),
			GENERIC_READ | GENERIC_WRITE, // access rights
			0,                            // don't share port
			0,                            // no security flags necessary
			OPEN_EXISTING,                // must exist to be opened
			0,					          // no overlapped operation
			0                             // no template file for COM ports
			);

		if (m_hPort == INVALID_HANDLE_VALUE)
		{
			handleError("opening serial port");
			m_hPort = 0;
		}
		else
		{
			LOG_INFO("Opened serial port " << m_strPortName);
		}
	}

	return isOpen();
}

bool SerialPort::isOpen() const
{
	return (m_hPort != 0);
}

bool SerialPort::close()
{
	if (isOpen())
	{
		if (::CloseHandle(m_hPort))
		{
			LOG_INFO("Closed serial port " << m_strPortName);
			m_hPort = 0;
		}
		else
		{
			handleError("closing serial port");
		}
	}
	return !isOpen();
}

bool SerialPort::setBaudrate(DWORD baudRate)
{
	bool success = false;

	if (isOpen())
	{
		DCB dcb = { 0 };
		dcb.DCBlength = sizeof(DCB);

		// read previous port state
		if (::GetCommState(m_hPort, &dcb))
		{
			// success > fill in new baudrate
			dcb.BaudRate = baudRate;
			dcb.ByteSize = 8;
			dcb.Parity   = NOPARITY;
			dcb.StopBits = ONESTOPBIT;
		}
		else
		{
			handleError("getting serial port state");
		}

		// set new baudrate
		if (::SetCommState(m_hPort, &dcb))
		{
			LOG_INFO("Set baudrate of serial port " << m_strPortName << " to " << baudRate);
			success = true;
		}
		else
		{
			handleError("setting serial port state");
		}
	}

	return success;
}

DWORD SerialPort::getTimeout() const
{
	DWORD timeout = 0;

	if (isOpen())
	{
		COMMTIMEOUTS timeouts = { 0 };

		// read previous timeouts
		if (::GetCommTimeouts(m_hPort, &timeouts))
		{
			// success > read timeout
			timeout = timeouts.ReadTotalTimeoutConstant;
		}
		else
		{
			handleError("getting serial port timeouts");
		}
	}

	return timeout;
}

bool SerialPort::setTimeout(DWORD timeout)
{
	bool success = false;

	if (isOpen())
	{
		COMMTIMEOUTS timeouts = { 0 };

		// read previous timeouts
		if (::GetCommTimeouts(m_hPort, &timeouts))
		{
			// success > change timeout
			timeouts.ReadTotalTimeoutConstant = timeout;
		}
		else
		{
			handleError("getting serial port timeouts");
		}

		// set new timeout values
		if (::SetCommTimeouts(m_hPort, &timeouts))
		{
			// LOG_INFO("Set timeout of serial port " << m_strPortName << " to " << timeout);
			success = true;
		}
		else
		{
			handleError("setting serial port timeouts");
		}
	}

	return success;
}

DWORD SerialPort::send(const void* pBuffer, DWORD nBytesToSend) const
{
	DWORD nBytesSent= 0;
	::WriteFile(m_hPort, pBuffer, nBytesToSend, &nBytesSent, NULL);
	return nBytesSent;
}

DWORD SerialPort::receive(void* pBuffer, DWORD nBytesToReceive) const
{
	DWORD nBytesReceived = 0;
	::ReadFile(m_hPort, pBuffer, nBytesToReceive, &nBytesReceived, NULL);
	return nBytesReceived;
}

SerialPort::~SerialPort()
{
	if (isOpen())
	{
		close();
	}
}

void SerialPort::handleError(const char* strFunction) const
{
	LPVOID lpMsgBuf;
	DWORD  error = GetLastError();

	FormatMessageW(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		error,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR) &lpMsgBuf,
		0, NULL
	);

	std::wstring strMsgW((const wchar_t*) lpMsgBuf);
	std::string  strMsg(strMsgW.begin(), strMsgW.end());
	LOG_ERROR("Error while " << strFunction << ": " << strMsg);

	LocalFree(lpMsgBuf);
}

<commit_msg>Only error messages for serial port<commit_after>
#include "SerialPort.h"
#include <ios>
#include <locale>

#include "Logging.h"
#undef   LOG_CLASS
#define  LOG_CLASS "SerialPort"

SerialPort::SerialPort(int portNumber) :
	m_iPortNumber(portNumber),
	m_hPort(0)
{
	// build short name from port number
	std::stringstream strPortName;
	strPortName << "COM" << m_iPortNumber;
	m_strPortName = strPortName.str();

	// build filename from port number
	std::stringstream strFileName;
	strFileName << "\\\\.\\COM" << m_iPortNumber;
	m_strFileName = strFileName.str();
}

bool SerialPort::exists() const
{
	// source: http://stackoverflow.com/questions/1205383/listing-serial-com-ports-on-windows

	std::wstring strPortNameW(m_strPortName.begin(), m_strPortName.end()); // convert to wchar
	COMMCONFIG config;
	DWORD      configSize = sizeof(config);
	// Port exists if configuration can be retrieved (returns true)
	// or the config structure size changes to indicate it was too small.
	return (GetDefaultCommConfigW(strPortNameW.c_str(), &config, &configSize) == TRUE) ||
	       (configSize != sizeof(config));
}

bool SerialPort::open()
{
	if (!isOpen())
	{
		std::wstring strFileNameW(m_strFileName.begin(), m_strFileName.end()); // convert to wchar
		m_hPort = ::CreateFile(
			strFileNameW.c_str(),
			GENERIC_READ | GENERIC_WRITE, // access rights
			0,                            // don't share port
			0,                            // no security flags necessary
			OPEN_EXISTING,                // must exist to be opened
			0,					          // no overlapped operation
			0                             // no template file for COM ports
			);

		if (m_hPort == INVALID_HANDLE_VALUE)
		{
			handleError("opening serial port");
			m_hPort = 0;
		}
		else
		{
			// LOG_INFO("Opened serial port " << m_strPortName);
		}
	}

	return isOpen();
}

bool SerialPort::isOpen() const
{
	return (m_hPort != 0);
}

bool SerialPort::close()
{
	if (isOpen())
	{
		if (::CloseHandle(m_hPort))
		{
			// LOG_INFO("Closed serial port " << m_strPortName);
			m_hPort = 0;
		}
		else
		{
			handleError("closing serial port");
		}
	}
	return !isOpen();
}

bool SerialPort::setBaudrate(DWORD baudRate)
{
	bool success = false;

	if (isOpen())
	{
		DCB dcb = { 0 };
		dcb.DCBlength = sizeof(DCB);

		// read previous port state
		if (::GetCommState(m_hPort, &dcb))
		{
			// success > fill in new baudrate
			dcb.BaudRate = baudRate;
			dcb.ByteSize = 8;
			dcb.Parity   = NOPARITY;
			dcb.StopBits = ONESTOPBIT;
		}
		else
		{
			handleError("getting serial port state");
		}

		// set new baudrate
		if (::SetCommState(m_hPort, &dcb))
		{
			// LOG_INFO("Set baudrate of serial port " << m_strPortName << " to " << baudRate);
			success = true;
		}
		else
		{
			handleError("setting serial port state");
		}
	}

	return success;
}

DWORD SerialPort::getTimeout() const
{
	DWORD timeout = 0;

	if (isOpen())
	{
		COMMTIMEOUTS timeouts = { 0 };

		// read previous timeouts
		if (::GetCommTimeouts(m_hPort, &timeouts))
		{
			// success > read timeout
			timeout = timeouts.ReadTotalTimeoutConstant;
		}
		else
		{
			handleError("getting serial port timeouts");
		}
	}

	return timeout;
}

bool SerialPort::setTimeout(DWORD timeout)
{
	bool success = false;

	if (isOpen())
	{
		COMMTIMEOUTS timeouts = { 0 };

		// read previous timeouts
		if (::GetCommTimeouts(m_hPort, &timeouts))
		{
			// success > change timeout
			timeouts.ReadTotalTimeoutConstant = timeout;
		}
		else
		{
			handleError("getting serial port timeouts");
		}

		// set new timeout values
		if (::SetCommTimeouts(m_hPort, &timeouts))
		{
			// LOG_INFO("Set timeout of serial port " << m_strPortName << " to " << timeout);
			success = true;
		}
		else
		{
			handleError("setting serial port timeouts");
		}
	}

	return success;
}

DWORD SerialPort::send(const void* pBuffer, DWORD nBytesToSend) const
{
	DWORD nBytesSent= 0;
	::WriteFile(m_hPort, pBuffer, nBytesToSend, &nBytesSent, NULL);
	return nBytesSent;
}

DWORD SerialPort::receive(void* pBuffer, DWORD nBytesToReceive) const
{
	DWORD nBytesReceived = 0;
	::ReadFile(m_hPort, pBuffer, nBytesToReceive, &nBytesReceived, NULL);
	return nBytesReceived;
}

SerialPort::~SerialPort()
{
	if (isOpen())
	{
		close();
	}
}

void SerialPort::handleError(const char* strFunction) const
{
	LPVOID lpMsgBuf;
	DWORD  error = GetLastError();

	FormatMessageW(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		error,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR) &lpMsgBuf,
		0, NULL
	);

	std::wstring strMsgW((const wchar_t*) lpMsgBuf);
	std::string  strMsg(strMsgW.begin(), strMsgW.end());
	LOG_ERROR("Error while " << strFunction << ": " << strMsg);

	LocalFree(lpMsgBuf);
}

<|endoftext|>


<commit_before><commit_msg>added handling for ports in mxid<commit_after><|endoftext|>


<commit_before>#include "Settings.h"

#include <Shlwapi.h>
#include <algorithm>

#include "Error.h"
#include "HotkeyActions.h"
#include "HotkeyInfo.h"
#include "Logger.h"
#include "Monitor.h"
#include "Skin.h"
#include "StringUtils.h"

#define XML_AUDIODEV "audioDeviceID"
#define XML_HIDE_WHENFULL "hideFullscreen"
#define XML_HIDEANIM "hideAnimation"
#define XML_HIDETIME "hideDelay"
#define XML_HIDESPEED "hideSpeed"
#define XML_LANGUAGE "language"
#define XML_MONITOR "monitor"
#define XML_NOTIFYICON "notifyIcon"
#define XML_ONTOP "onTop"
#define XML_OSD_OFFSET "osdEdgeOffset"
#define XML_OSD_POS "osdPosition"
#define XML_OSD_X "osdX"
#define XML_OSD_Y "osdY"
#define XML_SKIN "skin"
#define XML_SOUNDS "soundEffects"

std::wstring Settings::_appDir(L"");
Settings *Settings::instance;

std::vector<std::wstring> Settings::OSDPosNames = {
    L"top",
    L"left",
    L"right",
    L"bottom",
    L"center",
    L"top-left",
    L"top-right",
    L"bottom-left",
    L"bottom-right",
    L"custom"
};

std::vector<std::wstring> Settings::HideAnimNames = {
    L"none",
    L"fade"
};

Settings *Settings::Instance() {
    if (instance == NULL) {
        instance = new Settings();
    }
    return instance;
}

void Settings::Load() {
    _file = AppDir() + L"\\Settings.xml";
    CLOG(L"Loading settings: %s", _file.c_str());

    std::string u8FileName = StringUtils::Narrow(_file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        throw std::runtime_error("Failed to parse XML file");
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        throw std::runtime_error("Could not find root XML element");
    }

    delete _skin;
    _skin = new Skin(SkinXML());
}

int Settings::Save() {
    FILE *stream;
    errno_t err = _wfopen_s(&stream, _file.c_str(), L"w");
    if (err != 0) {
        CLOG(L"Could not open settings file for writing!");
        return 100 + err;
    }
    tinyxml2::XMLError result = _xml.SaveFile(stream);
    fclose(stream);
    return result;
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH];
        GetModuleFileName(NULL, path, MAX_PATH);
        PathRemoveFileSpec(path);
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SkinDir() {
    return AppDir() + L"\\" + SKIN_DIR;
}

std::wstring Settings::SettingsApp() {
    return Settings::AppDir() + L"\\" + SETTINGS_APP;
}

std::wstring Settings::LanguagesDir() {
    return AppDir() + L"\\" + LANG_DIR;
}

void Settings::LaunchSettingsApp() {
    std::wstring app = SettingsApp();

    CLOG(L"Opening Settings App: %s", app.c_str());
    int exec = (int) ShellExecute(
        NULL, L"open", app.c_str(), NULL, NULL, SW_SHOWNORMAL);

    if (exec <= 32) {
        Error::ErrorMessage(GENERR_NOTFOUND, app);
    }
}

std::wstring Settings::AudioDeviceID() {
    return GetText(XML_AUDIODEV);
}

std::wstring Settings::LanguageName() {
    std::wstring lang = GetText(XML_LANGUAGE);

    if (lang == L"") {
        return DEFAULT_LANGUAGE;
    } else {
        return lang;
    }
}

bool Settings::AlwaysOnTop() {
    return GetEnabled(XML_ONTOP);
}

void Settings::AlwaysOnTop(bool enable) {
    SetEnabled(XML_ONTOP, enable);
}

bool Settings::HideFullscreen() {
    return GetEnabled(XML_HIDE_WHENFULL);
}

void Settings::HideFullscreen(bool enable) {
    SetEnabled(XML_HIDE_WHENFULL, enable);
}

std::wstring Settings::Monitor() {
    return GetText(XML_MONITOR);
}

void Settings::Monitor(std::wstring monitorName) {
    SetText(XML_MONITOR, StringUtils::Narrow(monitorName));
}

int Settings::OSDEdgeOffset() {
    if (HasSetting(XML_OSD_OFFSET)) {
        return GetInt(XML_OSD_OFFSET);
    } else {
        return DEFAULT_OSD_OFFSET;
    }
}

void Settings::OSDEdgeOffset(int offset) {
    SetInt(XML_OSD_OFFSET, offset);
}

Settings::OSDPos Settings::OSDPosition() {
    std::wstring pos = GetText(XML_OSD_POS);
    std::transform(pos.begin(), pos.end(), pos.begin(), ::tolower);

    for (unsigned int i = 0; i < OSDPosNames.size(); ++i) {
        if (pos == OSDPosNames[i]) {
            return (Settings::OSDPos) i;
        }
    }

    return DEFAULT_OSD_POS;
}

void Settings::OSDPosition(OSDPos pos) {
    std::wstring posStr = OSDPosNames[(int) pos];
    SetText(XML_OSD_POS, StringUtils::Narrow(posStr));
}

int Settings::OSDX() {
    return GetInt(XML_OSD_X);
}

void Settings::OSDX(int x) {
    SetInt(XML_OSD_X, x);
}

int Settings::OSDY() {
    return GetInt(XML_OSD_Y);
}

void Settings::OSDY(int y) {
    SetInt(XML_OSD_Y, y);
}

Skin *Settings::CurrentSkin() {
    return _skin;
}

Settings::HideAnim Settings::HideAnimation() {
    std::wstring anim = GetText(XML_HIDEANIM);
    std::transform(anim.begin(), anim.end(), anim.begin(), ::tolower);

    for (unsigned int i = 0; i < HideAnimNames.size(); ++i) {
        if (anim == HideAnimNames[i]) {
            return (Settings::HideAnim) i;
        }
    }

    return DEFAULT_HIDE_ANIM;
}

void Settings::HideAnimation(Settings::HideAnim anim) {
    std::wstring hideStr = HideAnimNames[(int) anim];
    SetText(XML_HIDEANIM, StringUtils::Narrow(hideStr));
}

int Settings::HideDelay() {
    return GetInt(XML_HIDETIME);
}

void Settings::HideDelay(int delay) {
    SetInt(XML_HIDETIME, delay);
}

int Settings::HideSpeed() {
    return GetInt(XML_HIDESPEED);
}

void Settings::HideSpeed(int speed) {
    SetInt(XML_HIDESPEED, speed);
}

bool Settings::CurrentSkin(std::wstring skinName) {
    std::string name = StringUtils::Narrow(skinName);
    std::wstring xml = SkinXML(skinName);
    if (PathFileExists(xml.c_str()) == FALSE) {
        return false;
    }

    SetText(XML_SKIN, name);
    return true;
}

std::wstring Settings::SkinName() {
    std::wstring name = GetText("skin");

    if (name == L"") {
        return DEFAULT_SKIN;
    } else {
        return name;
    }
}

std::wstring Settings::SkinXML() {
    return SkinXML(SkinName());
}

std::wstring Settings::SkinXML(std::wstring skinName) {
    std::wstring skinXML = Settings::AppDir() + L"\\" + SKINS_DIR L"\\"
        + skinName + L"\\" SKIN_XML;
    return skinXML;
}

std::unordered_map<int, HotkeyInfo> Settings::Hotkeys() {
    std::unordered_map<int, HotkeyInfo> keyMappings;

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    if (hotkeys == NULL) {
        return keyMappings;
    }

    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");
    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        HotkeyInfo hki;
        hki.action = action;
        hki.keyCombination = combination;

        /* Does this hotkey action have any arguments? */
        tinyxml2::XMLElement *arg = hotkey->FirstChildElement("arg");
        for (; arg != NULL; arg = arg->NextSiblingElement()) {
            const char *argStr = arg->GetText();
            hki.args.push_back(StringUtils::Widen(argStr));
        }

        /* Whew, we made it! */
        CLOG(L"%s", hki.ToString().c_str());
        keyMappings[combination] = hki;
    }

    return keyMappings;
}

void Settings::Hotkeys(std::vector<HotkeyInfo> hotkeys) {
    tinyxml2::XMLElement *hkElem = GetOrCreateElement("hotkeys");
    hkElem->DeleteChildren();

    for (HotkeyInfo hotkey : hotkeys) {
        tinyxml2::XMLElement *hk = _xml.NewElement("hotkey");

        hk->SetAttribute("combination", hotkey.keyCombination);
        hk->SetAttribute("action", hotkey.action);

        if (hotkey.args.size() > 0) {
            for (std::wstring arg : hotkey.args) {
                tinyxml2::XMLElement *argElem = _xml.NewElement("arg");
                argElem->SetText(StringUtils::Narrow(arg).c_str());
                hk->InsertEndChild(argElem);
            }
        }

        hkElem->InsertEndChild(hk);
    }
}

bool Settings::NotifyIconEnabled() {
    return GetEnabled(XML_NOTIFYICON);
}

void Settings::NotifyIconEnabled(bool enable) {
    SetEnabled(XML_NOTIFYICON, enable);
}

bool Settings::SoundEffectsEnabled() {
    return GetEnabled(XML_SOUNDS);
}

void Settings::SoundEffectsEnabled(bool enable) {
    SetEnabled(XML_SOUNDS, enable);
}

bool Settings::HasSetting(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    return (el != NULL);
}

bool Settings::GetEnabled(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return false;
    } else {
        bool val = false;
        el->QueryBoolText(&val);
        return val;
    }
}

void Settings::SetEnabled(std::string elementName, bool enabled) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(enabled ? "true" : "false");
}

std::wstring Settings::GetText(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element %s not found",
            StringUtils::Widen(elementName).c_str());
        return L"";
    }

    const char* str = el->GetText();
    if (str == NULL) {
        return L"";
    } else {
        return StringUtils::Widen(str);
    }
}

void Settings::SetText(std::string elementName, std::string text) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(text.c_str());
}

int Settings::GetInt(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return 0;
    }

    int val = 0;
    el->QueryIntText(&val);
    return val;
}

void Settings::SetInt(std::string elementName, int value) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(value);
}

tinyxml2::XMLElement *Settings::GetOrCreateElement(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        el = _xml.NewElement(elementName.c_str());
        _root->InsertEndChild(el);
    }
    return el;
}<commit_msg>Initialize path array<commit_after>#include "Settings.h"

#include <Shlwapi.h>
#include <algorithm>

#include "Error.h"
#include "HotkeyActions.h"
#include "HotkeyInfo.h"
#include "Logger.h"
#include "Monitor.h"
#include "Skin.h"
#include "StringUtils.h"

#define XML_AUDIODEV "audioDeviceID"
#define XML_HIDE_WHENFULL "hideFullscreen"
#define XML_HIDEANIM "hideAnimation"
#define XML_HIDETIME "hideDelay"
#define XML_HIDESPEED "hideSpeed"
#define XML_LANGUAGE "language"
#define XML_MONITOR "monitor"
#define XML_NOTIFYICON "notifyIcon"
#define XML_ONTOP "onTop"
#define XML_OSD_OFFSET "osdEdgeOffset"
#define XML_OSD_POS "osdPosition"
#define XML_OSD_X "osdX"
#define XML_OSD_Y "osdY"
#define XML_SKIN "skin"
#define XML_SOUNDS "soundEffects"

std::wstring Settings::_appDir(L"");
Settings *Settings::instance;

std::vector<std::wstring> Settings::OSDPosNames = {
    L"top",
    L"left",
    L"right",
    L"bottom",
    L"center",
    L"top-left",
    L"top-right",
    L"bottom-left",
    L"bottom-right",
    L"custom"
};

std::vector<std::wstring> Settings::HideAnimNames = {
    L"none",
    L"fade"
};

Settings *Settings::Instance() {
    if (instance == NULL) {
        instance = new Settings();
    }
    return instance;
}

void Settings::Load() {
    _file = AppDir() + L"\\Settings.xml";
    CLOG(L"Loading settings: %s", _file.c_str());

    std::string u8FileName = StringUtils::Narrow(_file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        throw std::runtime_error("Failed to parse XML file");
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        throw std::runtime_error("Could not find root XML element");
    }

    delete _skin;
    _skin = new Skin(SkinXML());
}

int Settings::Save() {
    FILE *stream;
    errno_t err = _wfopen_s(&stream, _file.c_str(), L"w");
    if (err != 0) {
        CLOG(L"Could not open settings file for writing!");
        return 100 + err;
    }
    tinyxml2::XMLError result = _xml.SaveFile(stream);
    fclose(stream);
    return result;
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH] = { 0 };
        GetModuleFileName(NULL, path, MAX_PATH);
        PathRemoveFileSpec(path);
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SkinDir() {
    return AppDir() + L"\\" + SKIN_DIR;
}

std::wstring Settings::SettingsApp() {
    return Settings::AppDir() + L"\\" + SETTINGS_APP;
}

std::wstring Settings::LanguagesDir() {
    return AppDir() + L"\\" + LANG_DIR;
}

void Settings::LaunchSettingsApp() {
    std::wstring app = SettingsApp();

    CLOG(L"Opening Settings App: %s", app.c_str());
    int exec = (int) ShellExecute(
        NULL, L"open", app.c_str(), NULL, NULL, SW_SHOWNORMAL);

    if (exec <= 32) {
        Error::ErrorMessage(GENERR_NOTFOUND, app);
    }
}

std::wstring Settings::AudioDeviceID() {
    return GetText(XML_AUDIODEV);
}

std::wstring Settings::LanguageName() {
    std::wstring lang = GetText(XML_LANGUAGE);

    if (lang == L"") {
        return DEFAULT_LANGUAGE;
    } else {
        return lang;
    }
}

bool Settings::AlwaysOnTop() {
    return GetEnabled(XML_ONTOP);
}

void Settings::AlwaysOnTop(bool enable) {
    SetEnabled(XML_ONTOP, enable);
}

bool Settings::HideFullscreen() {
    return GetEnabled(XML_HIDE_WHENFULL);
}

void Settings::HideFullscreen(bool enable) {
    SetEnabled(XML_HIDE_WHENFULL, enable);
}

std::wstring Settings::Monitor() {
    return GetText(XML_MONITOR);
}

void Settings::Monitor(std::wstring monitorName) {
    SetText(XML_MONITOR, StringUtils::Narrow(monitorName));
}

int Settings::OSDEdgeOffset() {
    if (HasSetting(XML_OSD_OFFSET)) {
        return GetInt(XML_OSD_OFFSET);
    } else {
        return DEFAULT_OSD_OFFSET;
    }
}

void Settings::OSDEdgeOffset(int offset) {
    SetInt(XML_OSD_OFFSET, offset);
}

Settings::OSDPos Settings::OSDPosition() {
    std::wstring pos = GetText(XML_OSD_POS);
    std::transform(pos.begin(), pos.end(), pos.begin(), ::tolower);

    for (unsigned int i = 0; i < OSDPosNames.size(); ++i) {
        if (pos == OSDPosNames[i]) {
            return (Settings::OSDPos) i;
        }
    }

    return DEFAULT_OSD_POS;
}

void Settings::OSDPosition(OSDPos pos) {
    std::wstring posStr = OSDPosNames[(int) pos];
    SetText(XML_OSD_POS, StringUtils::Narrow(posStr));
}

int Settings::OSDX() {
    return GetInt(XML_OSD_X);
}

void Settings::OSDX(int x) {
    SetInt(XML_OSD_X, x);
}

int Settings::OSDY() {
    return GetInt(XML_OSD_Y);
}

void Settings::OSDY(int y) {
    SetInt(XML_OSD_Y, y);
}

Skin *Settings::CurrentSkin() {
    return _skin;
}

Settings::HideAnim Settings::HideAnimation() {
    std::wstring anim = GetText(XML_HIDEANIM);
    std::transform(anim.begin(), anim.end(), anim.begin(), ::tolower);

    for (unsigned int i = 0; i < HideAnimNames.size(); ++i) {
        if (anim == HideAnimNames[i]) {
            return (Settings::HideAnim) i;
        }
    }

    return DEFAULT_HIDE_ANIM;
}

void Settings::HideAnimation(Settings::HideAnim anim) {
    std::wstring hideStr = HideAnimNames[(int) anim];
    SetText(XML_HIDEANIM, StringUtils::Narrow(hideStr));
}

int Settings::HideDelay() {
    return GetInt(XML_HIDETIME);
}

void Settings::HideDelay(int delay) {
    SetInt(XML_HIDETIME, delay);
}

int Settings::HideSpeed() {
    return GetInt(XML_HIDESPEED);
}

void Settings::HideSpeed(int speed) {
    SetInt(XML_HIDESPEED, speed);
}

bool Settings::CurrentSkin(std::wstring skinName) {
    std::string name = StringUtils::Narrow(skinName);
    std::wstring xml = SkinXML(skinName);
    if (PathFileExists(xml.c_str()) == FALSE) {
        return false;
    }

    SetText(XML_SKIN, name);
    return true;
}

std::wstring Settings::SkinName() {
    std::wstring name = GetText("skin");

    if (name == L"") {
        return DEFAULT_SKIN;
    } else {
        return name;
    }
}

std::wstring Settings::SkinXML() {
    return SkinXML(SkinName());
}

std::wstring Settings::SkinXML(std::wstring skinName) {
    std::wstring skinXML = Settings::AppDir() + L"\\" + SKINS_DIR L"\\"
        + skinName + L"\\" SKIN_XML;
    return skinXML;
}

std::unordered_map<int, HotkeyInfo> Settings::Hotkeys() {
    std::unordered_map<int, HotkeyInfo> keyMappings;

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    if (hotkeys == NULL) {
        return keyMappings;
    }

    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");
    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        HotkeyInfo hki;
        hki.action = action;
        hki.keyCombination = combination;

        /* Does this hotkey action have any arguments? */
        tinyxml2::XMLElement *arg = hotkey->FirstChildElement("arg");
        for (; arg != NULL; arg = arg->NextSiblingElement()) {
            const char *argStr = arg->GetText();
            hki.args.push_back(StringUtils::Widen(argStr));
        }

        /* Whew, we made it! */
        CLOG(L"%s", hki.ToString().c_str());
        keyMappings[combination] = hki;
    }

    return keyMappings;
}

void Settings::Hotkeys(std::vector<HotkeyInfo> hotkeys) {
    tinyxml2::XMLElement *hkElem = GetOrCreateElement("hotkeys");
    hkElem->DeleteChildren();

    for (HotkeyInfo hotkey : hotkeys) {
        tinyxml2::XMLElement *hk = _xml.NewElement("hotkey");

        hk->SetAttribute("combination", hotkey.keyCombination);
        hk->SetAttribute("action", hotkey.action);

        if (hotkey.args.size() > 0) {
            for (std::wstring arg : hotkey.args) {
                tinyxml2::XMLElement *argElem = _xml.NewElement("arg");
                argElem->SetText(StringUtils::Narrow(arg).c_str());
                hk->InsertEndChild(argElem);
            }
        }

        hkElem->InsertEndChild(hk);
    }
}

bool Settings::NotifyIconEnabled() {
    return GetEnabled(XML_NOTIFYICON);
}

void Settings::NotifyIconEnabled(bool enable) {
    SetEnabled(XML_NOTIFYICON, enable);
}

bool Settings::SoundEffectsEnabled() {
    return GetEnabled(XML_SOUNDS);
}

void Settings::SoundEffectsEnabled(bool enable) {
    SetEnabled(XML_SOUNDS, enable);
}

bool Settings::HasSetting(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    return (el != NULL);
}

bool Settings::GetEnabled(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return false;
    } else {
        bool val = false;
        el->QueryBoolText(&val);
        return val;
    }
}

void Settings::SetEnabled(std::string elementName, bool enabled) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(enabled ? "true" : "false");
}

std::wstring Settings::GetText(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element %s not found",
            StringUtils::Widen(elementName).c_str());
        return L"";
    }

    const char* str = el->GetText();
    if (str == NULL) {
        return L"";
    } else {
        return StringUtils::Widen(str);
    }
}

void Settings::SetText(std::string elementName, std::string text) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(text.c_str());
}

int Settings::GetInt(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return 0;
    }

    int val = 0;
    el->QueryIntText(&val);
    return val;
}

void Settings::SetInt(std::string elementName, int value) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(value);
}

tinyxml2::XMLElement *Settings::GetOrCreateElement(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        el = _xml.NewElement(elementName.c_str());
        _root->InsertEndChild(el);
    }
    return el;
}<|endoftext|>


<commit_before>#include "Agent.h"
#include "Environment.h"
#include "Include.h"

using namespace std;

Agent::Agent(Environment* _world){

	srand( time(NULL) );
	running = false;

	steps = 0;

	posX = 0;
	posY = 0;

	world = _world;
	positionNode = _world->SetStartNode();
}

Agent::~Agent(void){

	delete positionNode;
}

int Agent::Run(){

	running = true;

	//running until environment is clean
	while (running) {
		system("CLS");
		world->draw(posX, posY);
		Vacuum();
		Move();

		//will end if taking more than 1k steps.
		steps++;
		if(steps > 1000) {
			running = false;
			return 0;
		}
	}
	return 1;
};

void Agent::Vacuum() {

	if ( positionNode->getValue() == 0 ) {
		//Sleep(300);
		cout << "Node is clean" << std::endl;
	}
	else {

		//Sleep(300);
		std::cout<< "I am vacuuming here now, soon clean...";
		//Sleep(300);
		std::cout<< " Clean!"<< std::endl;

		positionNode->setValue(0);
	}
}

void Agent::Move() {

	std::cout<< "Moving to next - ";

	//Sleep(1000);

	// TODO: Check for wals, dont move towards them!

	for(int i = 0; i < 4; i++) {

	}

	bool moveAble = true;
	int randomz;
	while( moveAble ) {
		randomz = rand() % 4;
		if(randomz == 0) { // Down
			cout<< "Down wards\n";
			if(world->isMoveAble(posX+1, posY)->getValue() != 2) {
				posX += 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
		else if(randomz == 1) { // Right
			cout<< "Right\n";
			if(world->isMoveAble(posX, posY+1)->getValue() != 2) {
				posY += 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
		else if(randomz == 2) { // Up
			cout<< "Up wards\n";
			if(world->isMoveAble(posX-1, posY)->getValue() != 2) {
				posX -= 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
		else if(randomz == 3) { // Left
			cout<< "Left\n";
			if(world->isMoveAble(posX, posY-1)->getValue() != 2) {
				posY -= 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
	}

	positionNode = world->isMoveAble(posX, posY);

	positionNode->visit();
	std::cout<< "Moved to x: "<<posX<< " y: "<< posY<<std::endl;

	Sleep(200);
	for(int i = 0; i < 4; i++) {

		moveToWhere[i] = false;
	}
}
<commit_msg>codetweak<commit_after>#include "Agent.h"
#include "Environment.h"
#include "Include.h"

using namespace std;

Agent::Agent(Environment* _world){

	srand( time(NULL) );
	running = false;

	steps = 0;

	posX = 0;
	posY = 0;

	world = _world;
	positionNode = _world->SetStartNode();
}

Agent::~Agent(void){

	delete positionNode;
}

int Agent::Run(){

	running = true;

	//running until environment is clean
	while (running) {
		system("CLS");
		world->draw(posX, posY);
		Vacuum();
		Move();

		//will end if taking more than 1k steps.
		steps++;
		if(steps > 1000) {
			running = false;
			return 0;
		}
	}
	return 1;
};

void Agent::Vacuum() {

	if ( positionNode->getValue() == 0 ) {
		//Sleep(300);
		cout << "Node is clean" << std::endl;
	}
	else {

		//Sleep(300);
		std::cout<< "I am vacuuming here now, soon clean...";
		//Sleep(300);
		std::cout<< " Clean!"<< std::endl;

		positionNode->setValue(0);
	}
}

void Agent::Move() {

	std::cout<< "Moving to next - ";

	//Sleep(1000);

	// TODO: Check for wals, dont move towards them!

	for(int i = 0; i < 4; i++) {

	}

	bool moveAble = true;
	int randomz;
	while( moveAble ) {
		randomz = rand() % 4;
		if(randomz == 0) { // Down
			cout<< "Down wards\n";
			if(world->isMoveAble(posX+1, posY)->getValue() != 2) {
				posX += 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
		else if(randomz == 1) { // Right
			cout<< "Right\n";
			if(world->isMoveAble(posX, posY+1)->getValue() != 2) {
				posY += 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
		else if(randomz == 2) { // Up
			cout<< "Up wards\n";
			if(world->isMoveAble(posX-1, posY)->getValue() != 2) {
				posX -= 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
		else if(randomz == 3) { // Left
			cout<< "Left\n";
			if(world->isMoveAble(posX, posY-1)->getValue() != 2) {
				posY -= 1;
				moveAble = false;
			} else {
					cout<< "Its a wall\n";
				}
		}
	}

	positionNode = world->isMoveAble(posX, posY);

	positionNode->visit();
	std::cout<< "Moved to x: "<<posX<< " y: "<< posY<<std::endl;
	Sleep(200);

	for(int i = 0; i < 4; i++) {
		moveToWhere[i] = false;
	}
}
<|endoftext|>


<commit_before>/**
 * Based on: https://github.com/davetcoleman/ros_control_boilerplate
 */

#include <kulbu_hardware/kulbu_hardware_interface.h>
#include <fcntl.h>
// #include <wiringPi.h>
// #include <softTone.h>

#define SYSFS_GPIO_DIR  "/sys/class/gpio"
#define SYSFS_PWM_DIR   "/sys/devices/platform/pwm-ctrl"
#define MAX_BUF 256

// Temp place-holder for some sysfs code.
int pwm_status(unsigned int pwm, bool enable) {
  int fd;
  char buf[MAX_BUF];

  // First check current value, only update if changed.
  char curr[11];
  int status;
  snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/enable%d", pwm);
  fd = open(buf, sizeof(buf), O_RDONLY);
  if (fd < 0) {
    perror("pwm/enable/read");
    return fd;
  }
  read(fd, curr, sizeof(curr));
  close(fd);

  // "On" always ends with "n".
  status = (curr[strlen(curr)-2] == 'n');

  if (status != enable) {
    ROS_INFO_STREAM_NAMED("kulbu_hardware_interface",
       "Chan: " << pwm << " Enable: " << enable);

    snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/enable%d", pwm);
    fd = open(buf, O_WRONLY);
    if (fd < 0) {
      perror("pwm/enable/write");
      return fd;
    }

    if (enable)
      write(fd, "1", 2);
    else
      write(fd, "0", 2);

    close(fd);
  }
  return 0;
}

int pwm_freq(unsigned int pwm, unsigned int freq) {
  int fd;
  char buf[MAX_BUF];

  // First check current value, only update if changed.
  char curr[11];
  int status;
  snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/freq%d", pwm);
  fd = open(buf, sizeof(buf), O_RDONLY);
  if (fd < 0) {
    perror("pwm/freq/read");
    return fd;
  }
  read(fd, curr, sizeof(curr));
  close(fd);

  if (atoi(curr) != freq && freq >= 1) {
    ROS_INFO_STREAM_NAMED("kulbu_hardware_interface",
       "Chan: " << pwm << " Freq: " << freq);

    snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/freq%d", pwm);
    fd = open(buf, O_WRONLY);
    if (fd < 0) {
      perror("pwm/freq/write");
      return fd;
    }

    int len = snprintf(buf, sizeof(buf), "%d", freq);
    write(fd, buf, len);
    close(fd);
  }
  return 0;
}

int gpio_set(unsigned int gpio, unsigned int value) {
  int fd;
  char buf[MAX_BUF];

  snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    perror("gpio/set-value");
    return fd;
  }

  if (value)
    write(fd, "1", 2);
  else
    write(fd, "0", 2);

  close(fd);
  return 0;
}

namespace kulbu_hardware {

KulbuHardwareInterface::KulbuHardwareInterface(
  ros::NodeHandle& nh,
  int joint_mode)
  : nh_(nh),
  joint_mode_(joint_mode) {
  // Initialize shared memory and interfaces here
  init();  // this implementation loads from rosparam

  ROS_INFO_NAMED("kulbu_hardware_interface",
    "Loaded kulbu_hardware_interface.");
}

void KulbuHardwareInterface::init() {
  ROS_INFO_STREAM_NAMED("kulbu_hardware_interface",
    "Reading rosparams from namespace: " << nh_.getNamespace());

  nh_.getParam("hardware_interface/steps_per_m", steps_per_m_);
  if (!steps_per_m_ > 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No step per metre found on parameter server."
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }

  // Get joint names
  nh_.getParam("hardware_interface/joints", joint_names_);
  if (joint_names_.size() == 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No joints found on parameter server"
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }
  num_joints_ = joint_names_.size();

  nh_.getParam("hardware_interface/dirs", pin_dirs_);
  if (pin_dirs_.size() == 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No GPIO direction pins found on parameter server."
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }

  nh_.getParam("hardware_interface/steps", pin_steps_);
  if (pin_steps_.size() == 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No GPIO step pins found on parameter server."
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }

  // Resize vectors
  joint_position_.resize(num_joints_);
  joint_velocity_.resize(num_joints_);
  joint_effort_.resize(num_joints_);
  joint_position_command_.resize(num_joints_);
  joint_velocity_command_.resize(num_joints_);
  joint_effort_command_.resize(num_joints_);

  // Initialise GPIO
  // wiringPiSetupSys();
  // FIXME: Ensure duty cycle is correct.
  // `512 > /sys/devices/platform/pwm-ctrl/duty0`

  // Initialize controller
  for (std::size_t i = 0; i < num_joints_; ++i) {
    ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
      "Loading joint name: " << joint_names_[i]);

    // Set direction pins to forward by default.
    // pinMode(pin_dirs_[i], OUTPUT);
    // digitalWrite(pin_dirs_[i], LOW);

    // Create PWM tone generator for joint
    // pinMode(pin_steps_[i], SOFT_TONE_OUTPUT);
    // softToneCreate(pin_steps_[i]);

    // Start with PWM turned off.
    pwm_status(pin_steps_[i], 0);
    // Start going forward.
    gpio_set(pin_dirs_[i], 0);

    // Create joint state interface
    joint_state_interface_.registerHandle(hardware_interface::JointStateHandle(
      joint_names_[i],
      &joint_position_[i],
      &joint_velocity_[i],
      &joint_effort_[i]));

    switch (joint_mode_) {
      case 0:
        // Create position joint interface
        position_joint_interface_
          .registerHandle(hardware_interface::JointHandle(
            joint_state_interface_.getHandle(
              joint_names_[i]),
              &joint_position_command_[i]));
        break;

      case 1:
        // Create velocity joint interface
        velocity_joint_interface_
          .registerHandle(hardware_interface::JointHandle(
            joint_state_interface_.getHandle(
              joint_names_[i]),
              &joint_velocity_command_[i]));
        break;

      case 2:
        // Create effort joint interface
        effort_joint_interface_
          .registerHandle(hardware_interface::JointHandle(
            joint_state_interface_.getHandle(
              joint_names_[i]),
              &joint_effort_command_[i]));
        break;
    }
  }

  registerInterface(&joint_state_interface_);  // From RobotHW base class.
  registerInterface(&position_joint_interface_);  // From RobotHW base class.
  registerInterface(&velocity_joint_interface_);  // From RobotHW base class.
  registerInterface(&effort_joint_interface_);  // From RobotHW base class.
}

void KulbuHardwareInterface::read(ros::Duration elapsed_time) {
  // Read the joint states from your hardware here
  // e.g.
  // for (std::size_t i = 0; i < num_joints_; ++i)
  // {
  //   joint_position_[i] = robot_api_.getJointPosition(i);
  //   joint_velocity_[i] = robot_api_.getJointVelocity(i);
  //   joint_effort_[i] = robot_api_.getJointEffort(i);
  // }
}

void KulbuHardwareInterface::write(ros::Duration elapsed_time) {
  int freq = 0;
  int dir = 0;

  // Send commands in different modes
  for (std::size_t i = 0; i < num_joints_; ++i) {
    // Skip joints with no pins defined
    if (pin_dirs_[i] == -1 || pin_steps_[i] == -1) continue;

    switch (joint_mode_) {
      case 1:  // hardware_interface::MODE_VELOCITY:
        // Calc PWM frequency.
        freq = joint_velocity_command_[i] * steps_per_m_;

        // Reverse flips direction.
        if (freq < 0) {
          freq = abs(freq);
          dir = 1;
        } else {
          dir = 0;
        }

        // Disable PWM when stopped.
        if (freq < 1) {
          freq = 0;
          pwm_status(pin_steps_[i], 0);
        // FIXME: Only if previously deactivated.
        } else {
          pwm_status(pin_steps_[i], 1);
        }

        // Set direction pin
        // digitalWrite(pin_dirs_[i], dir);
        gpio_set(pin_dirs_[i], dir);

        // Set PWM frequency
        // softToneWrite(pin_steps_[i], freq);
        pwm_freq(pin_steps_[i], freq);

        ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
          "\ni: "     << i <<
          "\ncmd: "   << joint_velocity_command_[i] <<
          "\ndist: "  << steps_per_m_ <<
          "\nfreq: "  << freq <<
          "\ndir: "   << dir <<
          "\njoint: " << joint_names_[i] <<
          "\ndir: "   << pin_dirs_[i] <<
          "\nstep: "  << pin_steps_[i]);
        break;

      default:
        ROS_ERROR_STREAM_NAMED("kulbu_hardware_interface",
          "Joint mode not implemented");
        break;
    }
  }
}

}  // namespace kulbu_hardware
<commit_msg>Cleanup and duty-cycle<commit_after>/**
 * Based on: https://github.com/davetcoleman/ros_control_boilerplate
 */

#include <kulbu_hardware/kulbu_hardware_interface.h>
#include <fcntl.h>

#define SYSFS_GPIO_DIR  "/sys/class/gpio"
#define SYSFS_PWM_DIR   "/sys/devices/platform/pwm-ctrl"
#define MAX_BUF 256

// FIXME: Encapsulate this IO code.
int pwm_enable(unsigned int pwm, bool enable) {
  int fd;
  char buf[MAX_BUF];

  // First check current value, only update if changed.
  char curr[11];
  int status;
  snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/enable%d", pwm);
  fd = open(buf, sizeof(buf), O_RDONLY);
  if (fd < 0) {
    perror("pwm/enable/read");
    return fd;
  }
  read(fd, curr, sizeof(curr));
  close(fd);

  // "On" always ends with an "n".
  status = (curr[strlen(curr)-2] == 'n');

  if (status != enable) {
    ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
       "Chan: " << pwm << " Enable: " << enable);

    snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/enable%d", pwm);
    fd = open(buf, O_WRONLY);
    if (fd < 0) {
      perror("pwm/enable/write");
      return fd;
    }

    if (enable)
      write(fd, "1", 2);
    else
      write(fd, "0", 2);

    close(fd);
  }
  return 0;
}

int pwm_freq(unsigned int pwm, unsigned int freq) {
  int fd;
  char buf[MAX_BUF];

  // First check current value, only update if changed.
  char curr[11];
  int status;
  snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/freq%d", pwm);
  fd = open(buf, sizeof(buf), O_RDONLY);
  if (fd < 0) {
    perror("pwm/freq/read");
    return fd;
  }
  read(fd, curr, sizeof(curr));
  close(fd);

  if (atoi(curr) != freq && freq >= 1) {
    ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
       "Chan: " << pwm << " Freq: " << freq);

    snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/freq%d", pwm);
    fd = open(buf, O_WRONLY);
    if (fd < 0) {
      perror("pwm/freq/write");
      return fd;
    }

    int len = snprintf(buf, sizeof(buf), "%d", freq);
    write(fd, buf, len);
    close(fd);
  }
  return 0;
}

int pwm_duty(unsigned int pwm, unsigned int duty) {
  int fd;
  char buf[MAX_BUF];

  ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
     "Chan: " << pwm << " Duty: " << duty);

  snprintf(buf, sizeof(buf), SYSFS_PWM_DIR  "/duty%d", pwm);
  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    perror("pwm/duty/write");
    return fd;
  }

  int len = snprintf(buf, sizeof(buf), "%d", duty);
  write(fd, buf, len);
  close(fd);

  return 0;
}

int gpio_set(unsigned int gpio, unsigned int value) {
  int fd;
  char buf[MAX_BUF];

  ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
     "GPIO: " << gpio << " Value: " << value);

  snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
  fd = open(buf, O_WRONLY);
  if (fd < 0) {
    perror("gpio/set-value");
    return fd;
  }

  if (value)
    write(fd, "1", 2);
  else
    write(fd, "0", 2);

  close(fd);
  return 0;
}

namespace kulbu_hardware {

KulbuHardwareInterface::KulbuHardwareInterface(
  ros::NodeHandle& nh,
  int joint_mode)
  : nh_(nh),
  joint_mode_(joint_mode) {
  // Initialize shared memory and interfaces here
  init();  // this implementation loads from rosparam

  ROS_INFO_NAMED("kulbu_hardware_interface",
    "Loaded kulbu_hardware_interface.");
}

void KulbuHardwareInterface::init() {
  ROS_INFO_STREAM_NAMED("kulbu_hardware_interface",
    "Reading rosparams from namespace: " << nh_.getNamespace());

  nh_.getParam("hardware_interface/steps_per_m", steps_per_m_);
  if (!steps_per_m_ > 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No step per metre found on parameter server."
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }

  // Get joint names
  nh_.getParam("hardware_interface/joints", joint_names_);
  if (joint_names_.size() == 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No joints found on parameter server"
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }
  num_joints_ = joint_names_.size();

  nh_.getParam("hardware_interface/dirs", pin_dirs_);
  if (pin_dirs_.size() == 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No GPIO direction pins found on parameter server."
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }

  nh_.getParam("hardware_interface/steps", pin_steps_);
  if (pin_steps_.size() == 0) {
    ROS_FATAL_STREAM_NAMED("kulbu_hardware_interface",
      "No GPIO step pins found on parameter server."
        << " Namespace: " << nh_.getNamespace());
    exit(-1);
  }

  // Resize vectors
  joint_position_.resize(num_joints_);
  joint_velocity_.resize(num_joints_);
  joint_effort_.resize(num_joints_);
  joint_position_command_.resize(num_joints_);
  joint_velocity_command_.resize(num_joints_);
  joint_effort_command_.resize(num_joints_);

  // Initialize controller
  for (std::size_t i = 0; i < num_joints_; ++i) {
    ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
      "Loading joint name: " << joint_names_[i]);

    // Start with PWM turned off and 50/50 duty cycle.
    pwm_enable(pin_steps_[i], 0);
    pwm_duty(pin_steps_[i], 512);

    // Set direction pins to forward by default.
    gpio_set(pin_dirs_[i], 0);

    // Create joint state interface
    joint_state_interface_.registerHandle(hardware_interface::JointStateHandle(
      joint_names_[i],
      &joint_position_[i],
      &joint_velocity_[i],
      &joint_effort_[i]));

    switch (joint_mode_) {
      case 0:
        // Create position joint interface
        position_joint_interface_
          .registerHandle(hardware_interface::JointHandle(
            joint_state_interface_.getHandle(
              joint_names_[i]),
              &joint_position_command_[i]));
        break;

      case 1:
        // Create velocity joint interface
        velocity_joint_interface_
          .registerHandle(hardware_interface::JointHandle(
            joint_state_interface_.getHandle(
              joint_names_[i]),
              &joint_velocity_command_[i]));
        break;

      case 2:
        // Create effort joint interface
        effort_joint_interface_
          .registerHandle(hardware_interface::JointHandle(
            joint_state_interface_.getHandle(
              joint_names_[i]),
              &joint_effort_command_[i]));
        break;
    }
  }

  registerInterface(&joint_state_interface_);  // From RobotHW base class.
  registerInterface(&position_joint_interface_);  // From RobotHW base class.
  registerInterface(&velocity_joint_interface_);  // From RobotHW base class.
  registerInterface(&effort_joint_interface_);  // From RobotHW base class.
}

void KulbuHardwareInterface::read(ros::Duration elapsed_time) {
  // Read the joint states from your hardware here
  // e.g.
  // for (std::size_t i = 0; i < num_joints_; ++i)
  // {
  //   joint_position_[i] = robot_api_.getJointPosition(i);
  //   joint_velocity_[i] = robot_api_.getJointVelocity(i);
  //   joint_effort_[i] = robot_api_.getJointEffort(i);
  // }
}

void KulbuHardwareInterface::write(ros::Duration elapsed_time) {
  int freq = 0;
  int dir = 0;

  // Send commands in different modes
  for (std::size_t i = 0; i < num_joints_; ++i) {
    // Skip joints with no pins defined
    if (pin_dirs_[i] == -1 || pin_steps_[i] == -1) continue;

    switch (joint_mode_) {
      case 1:  // hardware_interface::MODE_VELOCITY:
        // Calc PWM frequency.
        freq = joint_velocity_command_[i] * steps_per_m_;

        // Reverse flips direction.
        if (freq < 0) {
          freq = abs(freq);
          dir = 1;
        } else {
          dir = 0;
        }

        // Disable PWM when stopped.
        if (freq < 1) {
          freq = 0;
          pwm_enable(pin_steps_[i], 0);
        } else {
          pwm_enable(pin_steps_[i], 1);
        }

        // Set direction pin.
        gpio_set(pin_dirs_[i], dir);

        // Set PWM frequency.
        pwm_freq(pin_steps_[i], freq);

        ROS_DEBUG_STREAM_NAMED("kulbu_hardware_interface",
          "\ni: "     << i <<
          "\ncmd: "   << joint_velocity_command_[i] <<
          "\ndist: "  << steps_per_m_ <<
          "\nfreq: "  << freq <<
          "\ndir: "   << dir <<
          "\njoint: " << joint_names_[i] <<
          "\ndir: "   << pin_dirs_[i] <<
          "\nstep: "  << pin_steps_[i]);
        break;

      default:
        ROS_ERROR_STREAM_NAMED("kulbu_hardware_interface",
          "Joint mode not implemented");
        break;
    }
  }
}

}  // namespace kulbu_hardware
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include <string.h>
#include "condor_adtypes.h"

struct Lookup {
	char	str[20];
	AdTypes		type;
};
static const Lookup adtypes [] =
{
	{ QUILL_ADTYPE,			QUILL_AD, },
	{ STARTD_ADTYPE,		STARTD_AD, },
	{ SCHEDD_ADTYPE,		SCHEDD_AD, },
	{ MASTER_ADTYPE,		MASTER_AD, },
	{ GATEWAY_ADTYPE,		GATEWAY_AD, },
	{ CKPT_SRVR_ADTYPE,		CKPT_SRVR_AD, },
	{ STARTD_PVT_ADTYPE,	STARTD_PVT_AD, },
	{ SUBMITTER_ADTYPE,		SUBMITTOR_AD, },
	{ COLLECTOR_ADTYPE,		COLLECTOR_AD, },
	{ LICENSE_ADTYPE,		LICENSE_AD, },
	{ STORAGE_ADTYPE,		STORAGE_AD, },
	{ ANY_ADTYPE,			ANY_AD, },
	{ BOGUS_ADTYPE,			BOGUS_AD, },
	{ CLUSTER_ADTYPE,		CLUSTER_AD, },
	{ NEGOTIATOR_ADTYPE,	NEGOTIATOR_AD, },
	{ HAD_ADTYPE,			HAD_AD, },
	{ GENERIC_ADTYPE,		GENERIC_AD, },
	{ CREDD_ADTYPE,			CREDD_AD, },
	{ DATABASE_ADTYPE,		DATABASE_AD, },
	{ DBMSD_ADTYPE,			DBMSD_AD, },
	{ TT_ADTYPE,			TT_AD, },
	{ GRID_ADTYPE, 			GRID_AD, },
	{ XFER_SERVICE_ADTYPE,	XFER_SERVICE_AD, },
	{ LEASE_MANAGER_ADTYPE,	LEASE_MANAGER_AD, },
	{ "",		NO_AD, },
};

AdTypes
AdTypeFromString(const char* adtype_string)
{
	const Lookup	*v;
	for( v=adtypes;  v->type != NO_AD;  v++ ) {
		if( !strcasecmp(v->str, adtype_string) ) {
			return v->type;
		}
	}
	return NO_AD;
}

const char*
AdTypeToString( AdTypes type )
{
	if( (type >= (AdTypes)0)  &&  (type < NUM_AD_TYPES) ) {
		return adtypes[type].str;
	} else {
		return "Unknown";
	}
}
<commit_msg>Add missing ad types to Adtypes array<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include <string.h>
#include "condor_adtypes.h"

struct Lookup {
	char	str[20];
	AdTypes		type;
};
static const Lookup adtypes [] =
{
	{ QUILL_ADTYPE,			QUILL_AD, },
	{ STARTD_ADTYPE,		STARTD_AD, },
	{ SCHEDD_ADTYPE,		SCHEDD_AD, },
	{ MASTER_ADTYPE,		MASTER_AD, },
	{ GATEWAY_ADTYPE,		GATEWAY_AD, },
	{ CKPT_SRVR_ADTYPE,		CKPT_SRVR_AD, },
	{ STARTD_PVT_ADTYPE,	STARTD_PVT_AD, },
	{ SUBMITTER_ADTYPE,		SUBMITTOR_AD, },
	{ COLLECTOR_ADTYPE,		COLLECTOR_AD, },
	{ LICENSE_ADTYPE,		LICENSE_AD, },
	{ STORAGE_ADTYPE,		STORAGE_AD, },
	{ ANY_ADTYPE,			ANY_AD, },
	{ BOGUS_ADTYPE,			BOGUS_AD, },
	{ CLUSTER_ADTYPE,		CLUSTER_AD, },
	{ NEGOTIATOR_ADTYPE,	NEGOTIATOR_AD, },
	{ HAD_ADTYPE,			HAD_AD, },
	{ GENERIC_ADTYPE,		GENERIC_AD, },
	{ CREDD_ADTYPE,			CREDD_AD, },
	{ DATABASE_ADTYPE,		DATABASE_AD, },
	{ DBMSD_ADTYPE,			DBMSD_AD, },
	{ TT_ADTYPE,			TT_AD, },
	{ GRID_ADTYPE, 			GRID_AD, },
	{ XFER_SERVICE_ADTYPE,	XFER_SERVICE_AD, },
	{ LEASE_MANAGER_ADTYPE,	LEASE_MANAGER_AD, },
	{ DEFRAG_ADTYPE,		DEFRAG_AD, },
	{ ACCOUNTING_ADTYPE,	ACCOUNTING_AD, },
	{ "",		NO_AD, },
};

AdTypes
AdTypeFromString(const char* adtype_string)
{
	const Lookup	*v;
	for( v=adtypes;  v->type != NO_AD;  v++ ) {
		if( !strcasecmp(v->str, adtype_string) ) {
			return v->type;
		}
	}
	return NO_AD;
}

const char*
AdTypeToString( AdTypes type )
{
	if( (type >= (AdTypes)0)  &&  (type < NUM_AD_TYPES) ) {
		return adtypes[type].str;
	} else {
		return "Unknown";
	}
}
<|endoftext|>


<commit_before>#include "rdsstring.h"

#include <algorithm>

#include "data.h"

namespace redsea {

namespace {

std::string rtrim(std::string s) {
  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
  return s;
}

}

RDSString::RDSString(int len) : chars_(len), is_char_sequential_(len),
  prev_pos_(-1) {
  last_complete_string_ = getString();
}

void RDSString::setAt(int pos, int chr) {
  if (pos < 0 || pos >= (int)chars_.size())
    return;

  chars_[pos] = chr;

  if (pos != prev_pos_ + 1) {
    for (size_t i=0; i<is_char_sequential_.size(); i++)
      is_char_sequential_[i] = false;
  }

  is_char_sequential_[pos] = true;

  if (isComplete())
    last_complete_string_ = getString();

  prev_pos_ = pos;

}

size_t RDSString::lengthReceived() const {

  size_t result = 0;
  for (size_t i=0; i<is_char_sequential_.size(); i++) {
    if (!is_char_sequential_[i])
      break;
    result = i+1;
  }

  return result;
}

size_t RDSString::lengthExpected() const {

  size_t result = chars_.size();

  for (size_t i=0; i<chars_.size(); i++) {
    if (chars_[i] == 0x0D) {
      result = i;
      break;
    }
  }

  return result;
}

std::string RDSString::getString() const {
  std::string result;
  size_t len = lengthExpected();
  for (size_t i=0; i<len; i++) {
    result += (is_char_sequential_[i] ? getLCDchar(chars_[i]) : " ");
  }

  return result;

}

std::string RDSString::getTrimmedString() const {
  return rtrim(getString());
}

std::string RDSString::getLastCompleteString() const {
  return last_complete_string_;
}

std::string RDSString::getLastCompleteStringTrimmed() const {
  return rtrim(last_complete_string_);
}

bool RDSString::isComplete() const {
  return lengthReceived() >= lengthExpected();
}

void RDSString::clear() {
  for (size_t i=0; i<chars_.size(); i++) {
    is_char_sequential_[i] = false;
  }
  last_complete_string_ = getString();
}

} // namespace redsea
<commit_msg>this is C++17 stuff<commit_after>#include "rdsstring.h"

#include <algorithm>

#include "data.h"

namespace redsea {

namespace {

std::string rtrim(std::string s) {
  return s;
}

}

RDSString::RDSString(int len) : chars_(len), is_char_sequential_(len),
  prev_pos_(-1) {
  last_complete_string_ = getString();
}

void RDSString::setAt(int pos, int chr) {
  if (pos < 0 || pos >= (int)chars_.size())
    return;

  chars_[pos] = chr;

  if (pos != prev_pos_ + 1) {
    for (size_t i=0; i<is_char_sequential_.size(); i++)
      is_char_sequential_[i] = false;
  }

  is_char_sequential_[pos] = true;

  if (isComplete())
    last_complete_string_ = getString();

  prev_pos_ = pos;

}

size_t RDSString::lengthReceived() const {

  size_t result = 0;
  for (size_t i=0; i<is_char_sequential_.size(); i++) {
    if (!is_char_sequential_[i])
      break;
    result = i+1;
  }

  return result;
}

size_t RDSString::lengthExpected() const {

  size_t result = chars_.size();

  for (size_t i=0; i<chars_.size(); i++) {
    if (chars_[i] == 0x0D) {
      result = i;
      break;
    }
  }

  return result;
}

std::string RDSString::getString() const {
  std::string result;
  size_t len = lengthExpected();
  for (size_t i=0; i<len; i++) {
    result += (is_char_sequential_[i] ? getLCDchar(chars_[i]) : " ");
  }

  return result;

}

std::string RDSString::getTrimmedString() const {
  return rtrim(getString());
}

std::string RDSString::getLastCompleteString() const {
  return last_complete_string_;
}

std::string RDSString::getLastCompleteStringTrimmed() const {
  return rtrim(last_complete_string_);
}

bool RDSString::isComplete() const {
  return lengthReceived() >= lengthExpected();
}

void RDSString::clear() {
  for (size_t i=0; i<chars_.size(); i++) {
    is_char_sequential_[i] = false;
  }
  last_complete_string_ = getString();
}

} // namespace redsea
<|endoftext|>


<commit_before>#include "src/rdsstring.h"

#include <string>

#include "src/tables.h"

namespace redsea {

namespace {

std::string rtrim(std::string s) {
  return s.erase(s.find_last_not_of(' ')+1);
}

}

LCDchar::LCDchar() : code_(0) {
}

LCDchar::LCDchar(uint8_t _code) : code_(_code) {
}

uint8_t LCDchar::getCode() const {
  return code_;
}

std::string LCDchar::toString() const {
  return getLCDchar(code_);
}

RDSString::RDSString(int len) : chars_(len), is_char_sequential_(len),
  prev_pos_(-1), last_complete_string_(getString()) {
}

void RDSString::setAt(int pos, LCDchar chr) {
  if (pos < 0 || pos >= static_cast<int>(chars_.size()))
    return;

  chars_.at(pos) = chr;

  if (pos != prev_pos_ + 1) {
    for (size_t i=0; i < is_char_sequential_.size(); i++)
      is_char_sequential_[i] = false;
  }

  is_char_sequential_.at(pos) = true;

  if (isComplete()) {
    last_complete_string_ = getString();
    last_complete_chars_ = getChars();
  }

  prev_pos_ = pos;
}

std::string RDSString::charAt(int pos) const {
  return (pos < static_cast<int>(last_complete_chars_.size()) ?
      last_complete_chars_[pos].toString() : " ");
}

size_t RDSString::lengthReceived() const {
  size_t result = 0;
  for (size_t i=0; i < is_char_sequential_.size(); i++) {
    if (!is_char_sequential_[i])
      break;
    result = i+1;
  }

  return result;
}

size_t RDSString::lengthExpected() const {
  size_t result = chars_.size();

  for (size_t i=0; i < chars_.size(); i++) {
    if (chars_[i].getCode() == 0x0D) {
      result = i;
      break;
    }
  }

  return result;
}

void RDSString::resize(int n) {
  chars_.resize(n, 32);
}

std::string RDSString::getString() const {
  std::string result;
  for (LCDchar chr : getChars()) {
    result += chr.toString();
  }

  return result;
}

std::vector<LCDchar> RDSString::getChars() const {
  std::vector<LCDchar> result;
  size_t len = lengthExpected();
  for (size_t i=0; i < len; i++) {
    result.push_back(is_char_sequential_[i] ? chars_[i] : 32);
  }

  return result;
}

std::string RDSString::getTrimmedString() const {
  return rtrim(getString());
}

std::string RDSString::getLastCompleteString() const {
  return last_complete_string_;
}

std::string RDSString::getLastCompleteString(int start, int len) const {
  std::string result;
  for (int i=start; i < start+len; i++) {
    result += (i < static_cast<int>(last_complete_chars_.size()) ?
        last_complete_chars_[i].toString() : " ");
  }

  return result;
}

std::string RDSString::getLastCompleteStringTrimmed() const {
  return rtrim(last_complete_string_);
}

std::string RDSString::getLastCompleteStringTrimmed(int start, int len) const {
  return rtrim(getLastCompleteString(start, len));
}

bool RDSString::hasChars(int start, int len) const {
  return start+len <= static_cast<int>(last_complete_chars_.size());
}

bool RDSString::isComplete() const {
  return lengthReceived() >= lengthExpected();
}

void RDSString::clear() {
  for (size_t i=0; i < chars_.size(); i++) {
    is_char_sequential_[i] = false;
  }
  last_complete_string_ = getString();
  last_complete_chars_.clear();
}

}  // namespace redsea
<commit_msg>0x2 to signify ascii value<commit_after>#include "src/rdsstring.h"

#include <string>

#include "src/tables.h"

namespace redsea {

namespace {

std::string rtrim(std::string s) {
  return s.erase(s.find_last_not_of(' ')+1);
}

}

LCDchar::LCDchar() : code_(0) {
}

LCDchar::LCDchar(uint8_t _code) : code_(_code) {
}

uint8_t LCDchar::getCode() const {
  return code_;
}

std::string LCDchar::toString() const {
  return getLCDchar(code_);
}

RDSString::RDSString(int len) : chars_(len), is_char_sequential_(len),
  prev_pos_(-1), last_complete_string_(getString()) {
}

void RDSString::setAt(int pos, LCDchar chr) {
  if (pos < 0 || pos >= static_cast<int>(chars_.size()))
    return;

  chars_.at(pos) = chr;

  if (pos != prev_pos_ + 1) {
    for (size_t i=0; i < is_char_sequential_.size(); i++)
      is_char_sequential_[i] = false;
  }

  is_char_sequential_.at(pos) = true;

  if (isComplete()) {
    last_complete_string_ = getString();
    last_complete_chars_ = getChars();
  }

  prev_pos_ = pos;
}

std::string RDSString::charAt(int pos) const {
  return (pos < static_cast<int>(last_complete_chars_.size()) ?
      last_complete_chars_[pos].toString() : " ");
}

size_t RDSString::lengthReceived() const {
  size_t result = 0;
  for (size_t i=0; i < is_char_sequential_.size(); i++) {
    if (!is_char_sequential_[i])
      break;
    result = i+1;
  }

  return result;
}

size_t RDSString::lengthExpected() const {
  size_t result = chars_.size();

  for (size_t i=0; i < chars_.size(); i++) {
    if (chars_[i].getCode() == 0x0D) {
      result = i;
      break;
    }
  }

  return result;
}

void RDSString::resize(int n) {
  chars_.resize(n, 0x20);
}

std::string RDSString::getString() const {
  std::string result;
  for (LCDchar chr : getChars()) {
    result += chr.toString();
  }

  return result;
}

std::vector<LCDchar> RDSString::getChars() const {
  std::vector<LCDchar> result;
  size_t len = lengthExpected();
  for (size_t i=0; i < len; i++) {
    result.push_back(is_char_sequential_[i] ? chars_[i] : 32);
  }

  return result;
}

std::string RDSString::getTrimmedString() const {
  return rtrim(getString());
}

std::string RDSString::getLastCompleteString() const {
  return last_complete_string_;
}

std::string RDSString::getLastCompleteString(int start, int len) const {
  std::string result;
  for (int i=start; i < start+len; i++) {
    result += (i < static_cast<int>(last_complete_chars_.size()) ?
        last_complete_chars_[i].toString() : " ");
  }

  return result;
}

std::string RDSString::getLastCompleteStringTrimmed() const {
  return rtrim(last_complete_string_);
}

std::string RDSString::getLastCompleteStringTrimmed(int start, int len) const {
  return rtrim(getLastCompleteString(start, len));
}

bool RDSString::hasChars(int start, int len) const {
  return start+len <= static_cast<int>(last_complete_chars_.size());
}

bool RDSString::isComplete() const {
  return lengthReceived() >= lengthExpected();
}

void RDSString::clear() {
  for (size_t i=0; i < chars_.size(); i++) {
    is_char_sequential_[i] = false;
  }
  last_complete_string_ = getString();
  last_complete_chars_.clear();
}

}  // namespace redsea
<|endoftext|>