Monitor CMS2000 inverter via TCP/IP with USR-TCP232-E4 RS232/IP convertor

After months of waiting on hardware to arrive and playing around with different configurations, I have finally got my CMS2000 inverter to work through TCP/IP with POE.

RS232 to USB converter

The CMS2000 is a 2kW inverter with an RS232 connection for communications. If you simply want to view the data locally via a laptop, you will need a RS232 to USB adapter, specifically the Prolific USB-to-Serial Comm Port. Have a look at my review of RS232 to USB adapters for more info on the suitability of the converter.

RS232 to TCP/IP converter

Now, if you would rather run Ethernet to from the inverter and being able to read the values from any computer in your LAN, it is a little more complicated, but here is how.

The first thing you will need is a RS232 to TCP/IP converter, these can be purchased on eBay for about $25. Make sure you don’t simply get a serial to RJ45 cable, which are commonly used to configure managed switches. The model I received was the USR-TCP232-E45 by Jinan USR IOT Company China. The unit requires 5V power which I will discuss later.

The manual can be a little confusing, there is a test you can do if you have a com port or RS232 to USB adapter, where you basically create a loop and confirm it is all working. To get it talking to the CMS2000, configure the parameters of Port 0 (the RS232 port) as below. The main thing is to set it in TCP Server model. Configure the IP address and subnet as appropriate for your LAN.

Power

The RS232 to TCP/IP converter takes 5V DC, now you can run a separate 5V line to the inverter which isn’t ideal or use a passive injector to inject 5V into the line and split it out at the inverter, this is not IEEE 802.3af compliant though.   If your switch supports PoE you can split the power out directly at the inverter with a TP-LINK PoE splitter model TL-POE10R. This can be purchased for $14, and even includes the power and Ethernet cables needed to connect to the USR-TCP232-E45.

Software

To check the communications the CMS software ProControl can be used to check the communications prior to use with PVBeanCounter. Now, for some reason ProControl can’t connect directly via IP to the USR-TCP232-E45, fortunately I found a free virtual comm port software, which emulates a serial port connected to an IP address, the software is called VSP3 – Virtual Serial Port, developed by the HW group. Fairly easy to configure as below.

Final product

How to win at Markstrat (Markstrat Tips and Tricks) – Vodites

I will briefly share my learnings about the Vodites market.

My main view is to be the first to enter the market. The trick is to enter with the basic and least expensive product, as long as you are the only product in the market, the consumers will have no other choice but to purchase your product. The ad spend doesn’t have to be very high since there would be no competitors. Though you still need to maintain ad spent to increase the market size.

However, if a competitor happens to enter the market at the same time as you, then you won’t gain any market share, especially since the product would not meet ideal values.

The second advantage to entering the market with a basic product is when it is time to R&D the upgrade, you will notice significant (more than 50%) reduced costs. This makes it very easy to upgrade the product as soon as a competitor enters the market.

Target the largest markets first, Innovators and Early Adopters, they will also pay a premium for your products. A rough estimate for RRP for a Voditie product on launch is $1,000 or five times the base cost. If you are the only competitor, you may be able to charge even more.

Updated PHP code to automatically bid/buy an eBay auction item

Updated code to automatically bid on an eBay item, I’m currently using it myself if a loop of searched items.

Most of the changes are improved return status checking. For testing use one cent items with free shipping.

// MAIN BIDDING FUNCTION
// this function performs no checking on the input variables
// $username  -  the eBay user name
// $password  -  the eBay user password
// $item      -  the eBay item number to bid on
// $bid       -  the bid amount in local currency i.e. 5.67
// $link      -  referral link, can leave empty i.e. '' or use 'http://ebay.com'
function place_bid($username, $password, $item, $bid, $link) {

	$cookies = dirname(__FILE__).'/cookies.txt';
	
	//set success as default false
	$success = false;
	$bid_success = false;

	$curl = curl_init();
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20100101 Firefox/15.0.1');
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
	curl_setopt($curl, CURLOPT_REFERER, $link);
	curl_setopt($curl, CURLOPT_COOKIEFILE, $cookies);
	curl_setopt($curl, CURLOPT_COOKIEJAR, $cookies);
	
	//query the referal link page and grab tracking part
	curl_setopt($curl, CURLOPT_URL, $link);
	$ret = curl_exec ($curl);
	
	//query the sign-out page
	//curl_setopt($curl, CURLOPT_URL, "http://signin.ebay.com/ws/eBayISAPI.dll?SignIn&lgout=1");
	//$ret = curl_exec ($curl);
	
	//IMPORTANT		
	//query the sign-in page to set the cookies
	curl_setopt($curl, CURLOPT_URL, 'http://signin.ebay.com/aw-cgi/eBayISAPI.dll?SignIn&campid=5337161990&customid=7');
	curl_exec ($curl);
	
	//sign-in
	curl_setopt($curl, CURLOPT_URL, "http://signin.ebay.com/aw-cgi/eBayISAPI.dll?MfcISAPICommand=SignInWelcome&siteid=0&co_partnerId=2&UsingSSL=0&ru=&pp=&pa1=&pa2=&pa3=&i1=-1&pageType=-1&userid={$username}&pass={$password}&campid=5337161990&customid=7");
	$ret = curl_exec ($curl);
	if(curl_errno($curl)){
		ebaylog('Curl error: ' . curl_error($curl));
	}
	if (!$ret) {
		$ret = curl_exec ($curl);
		if(curl_errno($curl)){
			ebaylog('Curl error: ' . curl_error($curl));
		}
		if (!$ret) {
			$ret = curl_exec ($curl);
			if(curl_errno($curl)){
				ebaylog('Curl error: ' . curl_error($curl));
			}
		}
	}
	
	if (strpos($ret, "Member id {$username}") === FALSE) {
		if (preg_match('%<b class="altTitle">(.*)</b>%', $ret, $regs)) {
			$err = $regs[1];
			ebaylog("\"{$err}\"");
			if (strpos($err, 'The alerts below') === 0) {
				ebaylog("{$item}: 'The alerts below' found, successful");
				//set it to succes
			}
		} else {
			ebaylog("{$item}: Failed signing in");
			if (preg_match('%<font face=".*?" size="3"><b>(.*?)</b></font>%', $ret, $regs)) {
				$err = $regs[1];
				ebaylog("\"{$err}\"");
			}
			
			test_write($ret);
			goto end;
		}
		
		
	} else {
		ebaylog("{$item}: Success signing in");
	}
	
	
	//place the inital bid
	curl_setopt($curl, CURLOPT_URL, "http://offer.ebay.com/ws/eBayISAPI.dll?MakeBid&item={$item}&maxbid={$bid}&campid=5337161990&customid=7");
	$ret = curl_exec ($curl);
	if(curl_errno($curl)){
		ebaylog('Curl error: ' . curl_error($curl));
	}
	if (!$ret) {
		$ret = curl_exec ($curl);
	}

	if (preg_match_all('/(?:value="([-0-9a-zA-Z]*)" *)?name="stok"(?: *value="([-0-9a-zA-Z]*)")?/', $ret, $regs)) {
		$stok = $regs[1][0];
	} else {
		//Failed to get 'stok' value
		//try and determine why
		if (preg_match('%<div class="statusDiv">(.*?)</div>%', $ret, $regs)) {
			$err = $regs[1];
			ebaylog("'{$err}'");
			//if string starts with "Enter US $0.41 or more"
			if (stripos($err, 'Enter') === 0) {
				ebaylog("{$item}: 'Enter' found, aborting");
				//set it to success
				$success = true;
			} else if (stripos($err, 'To enter a') === 0) {
				ebaylog("{$item}: 'To enter a' found, aborting");
				//set it to success
				$success = true;
			} else if (stripos($err, 'Transaction Blocked') === 0) {
				ebaylog("{$item}: 'Transaction Blocked' found, aborting");
				//set it to success
				$success = true;
			}
			
		} else if (preg_match('%"\d*" - Invalid Item</div>%', $subject)) {
			ebaylog("{$item}: 'Invalid Item' found, aborting");
			test_write($ret);
			//set it to success
			$success = true;
		} else if (preg_match('%<div class="subTlt"><ul class="errList"><li>(.*?)</li></ul></div>%', $subject)) {
			ebaylog("{$item}: 'no longer available' found, aborting");
			test_write($ret);
			//set it to success
			$success = true;
		} else if (preg_match('%id="w\d-\d-_msg".*?>(.*?)</span>%', $ret, $regs)) {
			ebaylog("'{$regs[1]}'");
		} else if (preg_match('%<div\s+class\s*=\s*"(?:errRed|errBlk|errTitle|statusDiv)"\s*>(.*?)</div>%i', $ret, $regs)) {
			ebaylog("'{$regs[1]}'");
		} else {
			//don't know why so log the page
			ebaylog("{$item}: Failed to get 'stok' value");
			test_write($ret);
		}
		goto end;
	}
	
	if (preg_match_all('/(?:value="([-0-9a-zA-Z]*)" *)?name="uiid"(?: *value="([-0-9a-zA-Z]*)")?/', $ret, $regs)) {
		$uiid = $regs[1][0];
	} else {
		ebaylog("{$item}: Failed to get 'uiid' value");
		goto end;
	}
	

	if ($stok && $uiid) {
		ebaylog("{$item}: Success placing initial bid");
	} else {
		ebaylog("{$item}: Failed placing initial bid");
		goto end;
		
	}
	
	//confirm the bid
	curl_setopt($curl, CURLOPT_URL, "http://offer.ebay.com/ws/eBayISAPI.dll?MfcISAPICommand=MakeBid&maxbid={$bid}&quant=1&mode=1&stok={$stok}&uiid={$uiid}&co_partnerid=2&user={$username}&fb=0&item={$item}&campid=5337161990&customid=7");
	$ret = curl_exec ($curl);
	if(curl_errno($curl)){
		ebaylog('Curl error: ' . curl_error($curl));
	}
	if (!$ret) {
		$ret = curl_exec ($curl);
	}
	
	//perform a number of tests to determine if the bid was a success
	$bid_success = true;
	if (stripos($ret, "you're the first bidder") === FALSE) {
		if (stripos($ret, "you're the high bidder and currently in the lead") === FALSE) {
			if (stripos($ret, "you're currently the highest bidder") === FALSE) {
				$bid_success  = false;
				ebaylog("{$item}: Failed placing final bid");
				//try and determine why
				if (preg_match('%<div\s+class\s*=\s*"(?:errRed|errBlk|errTitle|statusDiv)"\s*>(.*?)</div>%i', $ret, $regs)) {
					$err = $regs[1];
					ebaylog("'{$err}'");
					if (stripos($err, 'Enter') === 0) {
						ebaylog("{$item}: 'Enter' found, aborting");
						//set it to success
						$bid_success = true;
					} else if (stripos($err, "You've just been outbid") === 0) {
						ebaylog("{$item}: 'You've just been outbid' found, aborting");
						//set it to success
						$bid_success  = true;
					} else if (stripos($err, "You're currently the high bidder,") === 0) {
						ebaylog("{$item}: 'You're currently the high bidder, but the reserve hasn't been met.' found, aborting");
						//set it to success
						$bid_success  = true;
					}
				} else {
					//we don't know why it failed so write the data
					test_write($ret);
				}
			}
		}
	}
	
	if ($bid_success) {
		ebaylog("{$item}: Success placing final bid");
		$success = true;
	}
	
	end:
	
	//close the curl session
	curl_close ($curl);
	
	if ($success) {
		ebaylog("{$item}: Success: {$username}");
	} else {
		ebaylog("{$item}: Failure: {$username}");
	}
	
	return $success;
}

//for testing
function test_write($out) {
	$fh = fopen(dirname(__FILE__).'/'.date('Y-m-d H-i-s').'.html', 'w');
	fwrite($fh, $out);
	fclose($fh);
}

//simple logging function
function ebaylog($msg) {
	$msg = "{$msg}\r\n";
	echo $msg;
	$fh = fopen(dirname(__FILE__).'/ebay-log.txt', 'a');
	fwrite($fh, date('Y-m-d H-i-s')." {$msg}");
	fclose($fh);
}

How to win at Markstrat (Markstrat Tips and Tricks) – competitor analysis

The last part in the How to win at Markstrat series, I will discuss competitor analysis and the various methods to speed up the analysis process.

In most cases Excel’s Conditional Formatting Colour Scales is all that is required. For the below examples blue is segment targeted. It is important to apply the conditional formatting over each market segment individually, not the entire market.

In other cases, a little bit of work is required, the square root of the sum of squared differences can be used to determine the distance between two points, in many cases this can be used to calculate how close a competitor is to ideal values. Excel makes this calculation easy with the SQRT(SUMXMY2()) formula.

Advertising

Advertising competitor analysis is the easiest, the Estimated Advertising Expenditures (in thousand dollars) gives a good indication to which company is targeting which segment.

Markstrat advertising competitor analysis

Commercial Team

Using the Estimated Commercial Team Size (in full-time equivalent), the exact commercial team size per channel of the competitors’ products can be determined.

Converting the distribution between each channel to a percentage, it can then be compared against the Shopping Habits found in the Consumer Survey. Using Excel’s SQRT(SUMXMY2()) we can get the difference between the ideal distribution and the actual for a particular product and segment. A lower value means closer ideal and actual.

Markstrat commercial team competitor analysis

The results show which company is targeting their products to which segment. But more importantly, which product has a more ideal commercial team distribution to meet a particular segment.

Semantic Scales

Similar can be done to semantic scales, which provides an indication to which products are ideal for the market segment. The two tables to use in the calculation are Brand Perceptions and Ideal Values.

Markstrat semantic scales competitor analysis

Multidimensional Scaling

Similar to Semantic Scales, the same can be done for Multidimensional Scaling. Ignoring the values, what is interesting is how similar the Multidimensional Scaling is to Semantic Scales seen through the similar shades of colours. Change Multidimensional Scaling Perceptions and you change Semantic Scales perceptions and vice versa.

Markstrat multidimensional scaling competitor analysis

How to win at Markstrat (Markstrat Tips and Tricks) – marketing strategy

The third part of this series looks at actual marketing strategy and marketing mix decisions.

I won’t go into too much marketing strategy detail, plus a lot of these are my thoughts from playing only a single round.

Segmentation

Target one product for one market segment only, early on it may be tempting to target multiple segments, particularly due to initial market share in many segments and purchase intentions in multiple segments.

Make a decision to target the single segment, the segment that will return the largest contribution. Targeting a single segment makes it easier to target your product for that specific segment. Since each segment has a different ideal characteristic product.

Estimated Expenditures

The total estimated advertising expenditure is correct, but about 10% of the total is added to each individual segment, this shouldn’t matter too much since it can be assumed competitors will be targeting one product per segment. The estimated advertising expenditure is extremely useful for determine competitor advertising spend, as well as competitor target segments.

The estimated commercial team is spot on in number.

Advertising

I have found that advertising is more important than commercial team.  Depending on your strategy, aim to at least match or trump your segment competitors total advertising spend in order to gain greater market dominance. If there are two competitors, aim to match their total spend, if budget permits of course.

I haven’t found it necessary to ever use No Objectives, unless you are launching a new product. It is easier to use multidimensional scaling compared to semantic scales since with multidimensional scaling you can alter multiple dimensions at the same time. with semantic scales you are limited to a maximum of two of the five characteristics.

You can change the perceptions of price, normally, if you want to match your product to ideal price you would change the price directly, the advantage of changing the price perceptions is you can increase the price above the segments ideal price, and then change the consumers perception of the price back to their ideals. If that makes sense, or simply, use the perceptions of price when you want to increase price.

Note, when you change a perception of a characteristic, you are changing the perception of the entire products market.  This is why some ideal perceptions change dramatically, other competitors are changing those perceptions.

Commercial Team

Commercial Team possibly reaches a maximum, where any additional persons provide no additional benefit. I have observed a team with a third more commercial team not gain any additional market share; the market share was exactly proportional to advertising spent instead. A possibly reason is commercial team isn’t segment specific, but over the entire market, so whilst they may be a large difference between you and a competitor, over the larger market the difference is small.

With commercial team, it is critical to distribute the commercial team using the Shopping Habits of the target segment. Though, this contradicts the Experiments which I will discuss below.

Experiments

The marketing experiments are useful for determining how to proportionate your budget. Though, it assumes the competitor actions remain the same, which is never the case.

I have contacted StratX to try and determine how they calculate estimated change in contribution, but they didn’t provide a definite answer, “Change in Contribution is equal to  Expected additional revenues minus Additional costs of advertising or commercial team. I will attempt show how it is calculated below.

Advertising Experiment

The Advertising Experiment calculates the increase in market share if advertising for a product was increased by 20%. An estimated expected change in contribution is provided, which is roughly calculated as Average Selling Price minus Average Unit Cost multiplies by the additional units sold (the addition of each segment of the Expected Change of Unit Market Share multiplied by the current period’s Market Size) subtract 20% of the current periods total Advertising spend.

(S_{Average Selling Price}-C_{Average Unit Cost}) \times N_{additional units sold}

Commercial Team Experiment

Similarly, the Commercial Team Experiment calculates the increase in market share if the commercial team was increased by 10 persons in each distribution channel.

This is where I haven’t got a definitive answer. The Expected Change in Number of Distributors is indirectly proportional to the Expected Change in Unit Market Share. This suggests that the Expected Change in Units Market Share is relevant to that specific distribution channel only. It even makes more sense, in that, when 10 persons are added to a distribution channel with low number of distributors compared to that with a high number of distributors, the increase in persons is a higher ratio, which explains why the units market share is higher (the indirect relationship).

What this means is, even though the percentage increase in Expected Change in Unit Market Share is the largest for a particular distribution channel, it doesn’t necessarily mean that is the distribution channel which should have the additional 10 persons.

The cost of 10 persons can be calculated using the market research, it is roughly $25,000.

The contribution of each distribution channel can be calculated as follows, using Savers segment as an example;

MARKET : SONITES : SAVERS Specialty Stores Mass Merchandisers Online Stores Total
Expected Change in unit Market Share (%U) 0.4% 0.0% 0.2%
Shopping Habits of Savers 19% 63% 18%
Savers next period Expected Market Size 229,068 761,136 221,796 1,212,000
Expected Change in Savers units 916 0 444 1,360
CM (average selling price minus average unit cost) 116
Expected Change in Contribution 105,831 0 51,236 157,067
Cost of 10 persons -250,000 -250,000 -250,000 -750,000

Proportioning Budget

Performing the above analysis on all products in all markets will give you an indication of where budget should be spent to maximise returns. It is also a good indication on where to decrease budget spend and even where you have overspent.

Using the experiments is only one indication, and should be used with previous competitor actions to determine the optimal strategy.